Full Code of hiteshchoudhary/apihub for AI

main e3a4414f1810 cached
548 files
8.7 MB
2.3M tokens
371 symbols
1 requests
Download .txt
Showing preview only (9,218K chars total). Download the full file or copy to clipboard to get everything.
Repository: hiteshchoudhary/apihub
Branch: main
Commit: e3a4414f1810
Files: 548
Total size: 8.7 MB

Directory structure:
gitextract_cp_asldb/

├── .babelrc
├── .commitlintrc.json
├── .dockerignore
├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.yaml
│       ├── code_coverage.yaml
│       ├── config.yml
│       ├── feature_request.yaml
│       └── frontend_contribution.yaml
├── .gitignore
├── .husky/
│   ├── commit-msg
│   └── pre-commit
├── .lintstagedrc
├── .prettierignore
├── .prettierrc
├── CONTRIBUTING.md
├── CONTRIBUTING_CODE_COVERAGE.md
├── CONTRIBUTING_FRONTEND.md
├── Dockerfile
├── LICENSE.md
├── README.md
├── docker-compose.prod.yml
├── docker-compose.yml
├── e2e/
│   ├── common.js
│   ├── db.js
│   ├── routes/
│   │   ├── apps/
│   │   │   └── todo.test.js
│   │   ├── healthcheck.test.js
│   │   └── seeds/
│   │       ├── chat-app.test.js
│   │       ├── ecommerce.test.js
│   │       ├── generated-credentials.test.js
│   │       ├── social-media.test.js
│   │       └── todo.test.js
│   └── test-server.js
├── examples/
│   ├── apps/
│   │   ├── auth/
│   │   │   └── .gitkeep
│   │   ├── chat-app/
│   │   │   └── web/
│   │   │       └── react-vite-tailwind/
│   │   │           ├── .eslintrc.cjs
│   │   │           ├── .gitignore
│   │   │           ├── README.md
│   │   │           ├── index.html
│   │   │           ├── package.json
│   │   │           ├── postcss.config.js
│   │   │           ├── src/
│   │   │           │   ├── App.tsx
│   │   │           │   ├── api/
│   │   │           │   │   └── index.ts
│   │   │           │   ├── components/
│   │   │           │   │   ├── Button.tsx
│   │   │           │   │   ├── Input.tsx
│   │   │           │   │   ├── Loader.tsx
│   │   │           │   │   ├── PrivateRoute.tsx
│   │   │           │   │   ├── PublicRoute.tsx
│   │   │           │   │   ├── Select.tsx
│   │   │           │   │   └── chat/
│   │   │           │   │       ├── AddChatModal.tsx
│   │   │           │   │       ├── ChatItem.tsx
│   │   │           │   │       ├── GroupChatDetailsModal.tsx
│   │   │           │   │       ├── MessageItem.tsx
│   │   │           │   │       └── Typing.tsx
│   │   │           │   ├── context/
│   │   │           │   │   ├── AuthContext.tsx
│   │   │           │   │   └── SocketContext.tsx
│   │   │           │   ├── index.css
│   │   │           │   ├── interfaces/
│   │   │           │   │   ├── api.ts
│   │   │           │   │   ├── chat.ts
│   │   │           │   │   └── user.ts
│   │   │           │   ├── main.tsx
│   │   │           │   ├── pages/
│   │   │           │   │   ├── chat.tsx
│   │   │           │   │   ├── login.tsx
│   │   │           │   │   └── register.tsx
│   │   │           │   ├── utils/
│   │   │           │   │   └── index.ts
│   │   │           │   └── vite-env.d.ts
│   │   │           ├── tailwind.config.js
│   │   │           ├── tsconfig.json
│   │   │           ├── tsconfig.node.json
│   │   │           └── vite.config.ts
│   │   ├── ecommerce/
│   │   │   ├── .gitkeep
│   │   │   └── web/
│   │   │       └── react-vite-redux-tailwind/
│   │   │           ├── .eslintrc.cjs
│   │   │           ├── .gitignore
│   │   │           ├── README.md
│   │   │           ├── index.html
│   │   │           ├── package.json
│   │   │           ├── postcss.config.js
│   │   │           ├── public/
│   │   │           │   └── locales/
│   │   │           │       ├── ar/
│   │   │           │       │   └── translation.json
│   │   │           │       ├── en/
│   │   │           │       │   └── translation.json
│   │   │           │       └── hn/
│   │   │           │           └── translation.json
│   │   │           ├── src/
│   │   │           │   ├── App.tsx
│   │   │           │   ├── RoutePaths.tsx
│   │   │           │   ├── components/
│   │   │           │   │   ├── basic/
│   │   │           │   │   │   ├── ArrowButton.tsx
│   │   │           │   │   │   ├── Button.tsx
│   │   │           │   │   │   ├── CarouselButtons.tsx
│   │   │           │   │   │   ├── Checkbox.tsx
│   │   │           │   │   │   ├── DateRangePicker.tsx
│   │   │           │   │   │   ├── Drawer.tsx
│   │   │           │   │   │   ├── Dropdown.tsx
│   │   │           │   │   │   ├── ErrorMessage.tsx
│   │   │           │   │   │   ├── FullPageLoadingSpinner.tsx
│   │   │           │   │   │   ├── Hamburger.tsx
│   │   │           │   │   │   ├── Image.tsx
│   │   │           │   │   │   ├── Input.tsx
│   │   │           │   │   │   ├── Link.tsx
│   │   │           │   │   │   ├── Modal.tsx
│   │   │           │   │   │   ├── NavItem.tsx
│   │   │           │   │   │   ├── NavList.tsx
│   │   │           │   │   │   ├── RadioButtons.tsx
│   │   │           │   │   │   ├── RoundedIcon.tsx
│   │   │           │   │   │   ├── SearchInput.tsx
│   │   │           │   │   │   ├── SelectionMenu.tsx
│   │   │           │   │   │   ├── TabItem.tsx
│   │   │           │   │   │   ├── Tabs.tsx
│   │   │           │   │   │   ├── Text.tsx
│   │   │           │   │   │   └── ToastMessage.tsx
│   │   │           │   │   ├── business/
│   │   │           │   │   │   ├── AddressCard.tsx
│   │   │           │   │   │   ├── AddressCardList.tsx
│   │   │           │   │   │   ├── CardContainer.tsx
│   │   │           │   │   │   ├── CartItem.tsx
│   │   │           │   │   │   ├── CartItemList.tsx
│   │   │           │   │   │   ├── CartSummary.tsx
│   │   │           │   │   │   ├── CategoryCard.tsx
│   │   │           │   │   │   ├── CompanyGurantee.tsx
│   │   │           │   │   │   ├── CouponCard.tsx
│   │   │           │   │   │   ├── CouponCardList.tsx
│   │   │           │   │   │   ├── FooterSection.tsx
│   │   │           │   │   │   ├── InvoiceAmountSummary.tsx
│   │   │           │   │   │   ├── OrderCard.tsx
│   │   │           │   │   │   ├── OrderItem.tsx
│   │   │           │   │   │   ├── OrderItemList.tsx
│   │   │           │   │   │   ├── OrderListFilters.tsx
│   │   │           │   │   │   ├── OrderSummary.tsx
│   │   │           │   │   │   ├── OrdersList.tsx
│   │   │           │   │   │   ├── Payment.tsx
│   │   │           │   │   │   ├── ProductCard.tsx
│   │   │           │   │   │   ├── ProductFilters.tsx
│   │   │           │   │   │   ├── ProductImagesView.tsx
│   │   │           │   │   │   ├── ProductList.tsx
│   │   │           │   │   │   ├── QuantityCounter.tsx
│   │   │           │   │   │   └── Timer.tsx
│   │   │           │   │   ├── icons/
│   │   │           │   │   │   ├── AccountIcon.tsx
│   │   │           │   │   │   ├── AddIcon.tsx
│   │   │           │   │   │   ├── CartIcon.tsx
│   │   │           │   │   │   ├── CloseIcon.tsx
│   │   │           │   │   │   ├── DeleteIcon.tsx
│   │   │           │   │   │   ├── DownArrow.tsx
│   │   │           │   │   │   ├── EditIcon.tsx
│   │   │           │   │   │   ├── ErrorIcon.tsx
│   │   │           │   │   │   ├── GeneralCategoryIcon.tsx
│   │   │           │   │   │   ├── GoogleIcon.tsx
│   │   │           │   │   │   ├── GuranteeIcon.tsx
│   │   │           │   │   │   ├── HamburgerIcon.tsx
│   │   │           │   │   │   ├── HeadphoneIcon.tsx
│   │   │           │   │   │   ├── HidePasswordIcon.tsx
│   │   │           │   │   │   ├── LeftArrow.tsx
│   │   │           │   │   │   ├── LoadingSpinner.tsx
│   │   │           │   │   │   ├── LogoutIcon.tsx
│   │   │           │   │   │   ├── OrderIcon.tsx
│   │   │           │   │   │   ├── RectangleIcon.tsx
│   │   │           │   │   │   ├── SearchIcon.tsx
│   │   │           │   │   │   ├── ShowPasswordIcon.tsx
│   │   │           │   │   │   ├── SubtractIcon.tsx
│   │   │           │   │   │   ├── TickIcon.tsx
│   │   │           │   │   │   ├── TruckIcon.tsx
│   │   │           │   │   │   └── UpArrow.tsx
│   │   │           │   │   ├── modals/
│   │   │           │   │   │   ├── addaddressmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── AddAddressModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── AddAddressModal.tsx
│   │   │           │   │   │   ├── changepasswordmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── ChangePasswordModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── ChangePasswordModal.tsx
│   │   │           │   │   │   ├── deleteaddressmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── DeleteAddressModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── DeleteAddressModal.tsx
│   │   │           │   │   │   ├── feedbackmodal/
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── FeedbackModal.tsx
│   │   │           │   │   │   ├── forgotpasswordmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── ForgotPasswordModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── ForgotPasswordModal.tsx
│   │   │           │   │   │   └── logoutmodal/
│   │   │           │   │   │       ├── container/
│   │   │           │   │   │       │   └── LogoutModalContainer.tsx
│   │   │           │   │   │       └── presentation/
│   │   │           │   │   │           └── LogoutModal.tsx
│   │   │           │   │   └── widgets/
│   │   │           │   │       ├── about/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── AboutContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── About.tsx
│   │   │           │   │       ├── allproductlist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── AllProductListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── AllProductList.tsx
│   │   │           │   │       ├── banner/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── BannerContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Banner.tsx
│   │   │           │   │       ├── cart/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CartContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Cart.tsx
│   │   │           │   │       ├── categorylist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CategoryListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── CategoryList.tsx
│   │   │           │   │       ├── checkout/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CheckoutContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Checkout.tsx
│   │   │           │   │       ├── companyguranteelist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CompanyGuranteeListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── CompanyGuranteeList.tsx
│   │   │           │   │       ├── editaddresses/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── EditAddressesContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── EditAddresses.tsx
│   │   │           │   │       ├── editprofile/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── EditProfileContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── EditProfile.tsx
│   │   │           │   │       ├── exploreproductlist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── ExploreProductListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── ExploreProductList.tsx
│   │   │           │   │       ├── featuredproductlist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── FeaturedProductListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── FeaturedProductList.tsx
│   │   │           │   │       ├── footer/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── FooterContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Footer.tsx
│   │   │           │   │       ├── header/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── HeaderContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Header.tsx
│   │   │           │   │       ├── infoheader/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── InfoHeaderContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── InfoHeader.tsx
│   │   │           │   │       ├── login/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── LoginContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Login.tsx
│   │   │           │   │       ├── myaccountoption/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── MyAccountOptionContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── MyAccountOption.tsx
│   │   │           │   │       ├── myorderslist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── MyOrdersListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── MyOrdersList.tsx
│   │   │           │   │       ├── orderdetail/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── OrderDetailContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── OrderDetail.tsx
│   │   │           │   │       ├── productdetails/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── ProductDetailsContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── ProductDetails.tsx
│   │   │           │   │       ├── relateditemslist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── RelatedItemsListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── RelatedItemsList.tsx
│   │   │           │   │       ├── resetforgottenpassword/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── ResetForgottenPasswordContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── ResetForgottenPassword.tsx
│   │   │           │   │       └── signup/
│   │   │           │   │           ├── container/
│   │   │           │   │           │   └── SignupContainer.tsx
│   │   │           │   │           └── presentation/
│   │   │           │   │               └── Signup.tsx
│   │   │           │   ├── constants.ts
│   │   │           │   ├── data/
│   │   │           │   │   └── applicationData.tsx
│   │   │           │   ├── hooks/
│   │   │           │   │   ├── useBreakpointCheck.tsx
│   │   │           │   │   ├── useCustomNavigate.tsx
│   │   │           │   │   ├── useOnRefresh.tsx
│   │   │           │   │   └── useOutsideClick.tsx
│   │   │           │   ├── i18n.ts
│   │   │           │   ├── index.css
│   │   │           │   ├── layouts/
│   │   │           │   │   └── PageLayout.tsx
│   │   │           │   ├── main.tsx
│   │   │           │   ├── pages/
│   │   │           │   │   ├── about/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── AboutPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── AboutPage.tsx
│   │   │           │   │   ├── cart/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── CartPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── CartPage.tsx
│   │   │           │   │   ├── checkout/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── CheckoutPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── CheckoutPage.tsx
│   │   │           │   │   ├── home/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── HomePageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── HomePage.tsx
│   │   │           │   │   ├── login/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── LoginPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── LoginPage.tsx
│   │   │           │   │   ├── manageaccount/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ManageAccountPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ManageAccountPage.tsx
│   │   │           │   │   ├── orderdetail/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── OrderDetailPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── OrderDetailPage.tsx
│   │   │           │   │   ├── orders/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── OrdersPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── OrdersPage.tsx
│   │   │           │   │   ├── pagenotfound/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── PageNotFoundPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── PageNotFoundPage.tsx
│   │   │           │   │   ├── paymentfeedback/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── PaymentFeedbackPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── PaymentFeedbackPage.tsx
│   │   │           │   │   ├── productdetail/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ProductDetailPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ProductDetailPage.tsx
│   │   │           │   │   ├── products/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ProductsPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ProductsPage.tsx
│   │   │           │   │   ├── productsearch/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ProductSearchPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ProductSearchPage.tsx
│   │   │           │   │   ├── resetforgottenpassword/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ResetForgottenPasswordPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ResetForgottenPasswordPage.tsx
│   │   │           │   │   └── signup/
│   │   │           │   │       ├── container/
│   │   │           │   │       │   └── SignupPageContainer.tsx
│   │   │           │   │       └── presentation/
│   │   │           │   │           └── SignupPage.tsx
│   │   │           │   ├── protectedroutes/
│   │   │           │   │   └── ForLoggedInUsers.tsx
│   │   │           │   ├── services/
│   │   │           │   │   ├── ApiError.ts
│   │   │           │   │   ├── ApiRequest.ts
│   │   │           │   │   ├── ApiResponse.ts
│   │   │           │   │   ├── CountryApiRequest.ts
│   │   │           │   │   ├── address/
│   │   │           │   │   │   ├── AddressService.ts
│   │   │           │   │   │   └── AddressTypes.ts
│   │   │           │   │   ├── auth/
│   │   │           │   │   │   ├── AuthService.ts
│   │   │           │   │   │   └── AuthTypes.ts
│   │   │           │   │   ├── cart/
│   │   │           │   │   │   ├── CartService.ts
│   │   │           │   │   │   └── CartTypes.ts
│   │   │           │   │   ├── category/
│   │   │           │   │   │   ├── CategoryService.ts
│   │   │           │   │   │   └── CategoryTypes.ts
│   │   │           │   │   ├── countryapi/
│   │   │           │   │   │   ├── CountryApiService.ts
│   │   │           │   │   │   └── CountryApiTypes.ts
│   │   │           │   │   ├── coupon/
│   │   │           │   │   │   ├── CouponService.ts
│   │   │           │   │   │   └── CouponTypes.ts
│   │   │           │   │   ├── order/
│   │   │           │   │   │   ├── OrderService.ts
│   │   │           │   │   │   └── OrderTypes.ts
│   │   │           │   │   ├── product/
│   │   │           │   │   │   ├── ProductService.ts
│   │   │           │   │   │   └── ProductTypes.ts
│   │   │           │   │   └── profile/
│   │   │           │   │       ├── ProfileService.ts
│   │   │           │   │       └── ProfileTypes.ts
│   │   │           │   ├── store/
│   │   │           │   │   ├── AuthSlice.ts
│   │   │           │   │   ├── BreakpointSlice.ts
│   │   │           │   │   ├── CartSlice.ts
│   │   │           │   │   ├── LanguageSlice.ts
│   │   │           │   │   ├── ToastMessageSlice.ts
│   │   │           │   │   └── index.ts
│   │   │           │   ├── styles/
│   │   │           │   │   └── DateRangePicker.css
│   │   │           │   ├── utils/
│   │   │           │   │   ├── asyncHandler.ts
│   │   │           │   │   ├── breakpointsHelper.ts
│   │   │           │   │   ├── commonHelper.ts
│   │   │           │   │   ├── countryApiAsyncHandler.ts
│   │   │           │   │   ├── dateTimeHelper.ts
│   │   │           │   │   └── languageHelpers.ts
│   │   │           │   └── vite-env.d.ts
│   │   │           ├── tailwind.config.js
│   │   │           ├── tsconfig.json
│   │   │           ├── tsconfig.node.json
│   │   │           └── vite.config.ts
│   │   ├── social-media/
│   │   │   └── .gitkeep
│   │   └── todo/
│   │       └── web/
│   │           └── react-vite-tailwind/
│   │               ├── .eslintrc.cjs
│   │               ├── .gitignore
│   │               ├── README.md
│   │               ├── index.html
│   │               ├── package.json
│   │               ├── postcss.config.js
│   │               ├── src/
│   │               │   ├── App.tsx
│   │               │   ├── api/
│   │               │   │   └── index.ts
│   │               │   ├── components/
│   │               │   │   ├── Button.tsx
│   │               │   │   ├── Header.tsx
│   │               │   │   ├── Input.tsx
│   │               │   │   ├── Loader.tsx
│   │               │   │   ├── ModalContainer.tsx
│   │               │   │   ├── Options.tsx
│   │               │   │   └── todos/
│   │               │   │       ├── CreateTodoModal.tsx
│   │               │   │       ├── DetailAndEditModal.tsx
│   │               │   │       ├── TabsHeader.tsx
│   │               │   │       └── TodoCard.tsx
│   │               │   ├── context/
│   │               │   │   └── TodoContext.tsx
│   │               │   ├── index.css
│   │               │   ├── interfaces/
│   │               │   │   ├── api.ts
│   │               │   │   └── todo.ts
│   │               │   ├── main.tsx
│   │               │   ├── utils/
│   │               │   │   └── index.ts
│   │               │   └── vite-env.d.ts
│   │               ├── tailwind.config.js
│   │               ├── tsconfig.json
│   │               ├── tsconfig.node.json
│   │               └── vite.config.ts
│   ├── kitchen-sink/
│   │   ├── cookies/
│   │   │   └── .gitkeep
│   │   ├── httpmethods/
│   │   │   └── .gitkeep
│   │   ├── images/
│   │   │   └── .gitkeep
│   │   ├── redirects/
│   │   │   └── .gitkeep
│   │   ├── requestinspections/
│   │   │   └── .gitkeep
│   │   ├── responseinspections/
│   │   │   └── .gitkeep
│   │   └── statuscodes/
│   │       └── web/
│   │           └── react-shadcn-tailwind-zustand/
│   │               ├── .eslintrc.cjs
│   │               ├── .gitignore
│   │               ├── README.md
│   │               ├── components.json
│   │               ├── index.html
│   │               ├── package.json
│   │               ├── postcss.config.js
│   │               ├── src/
│   │               │   ├── App.css
│   │               │   ├── App.tsx
│   │               │   ├── components/
│   │               │   │   └── ui/
│   │               │   │       ├── accordion.tsx
│   │               │   │       ├── button.tsx
│   │               │   │       ├── card.tsx
│   │               │   │       ├── command.tsx
│   │               │   │       ├── dialog.tsx
│   │               │   │       ├── label.tsx
│   │               │   │       ├── navigation-menu.tsx
│   │               │   │       ├── popover.tsx
│   │               │   │       ├── radio-group.tsx
│   │               │   │       └── select.tsx
│   │               │   ├── constants/
│   │               │   │   ├── index.ts
│   │               │   │   └── types.ts
│   │               │   ├── index.css
│   │               │   ├── layout/
│   │               │   │   ├── header/
│   │               │   │   │   ├── Header.tsx
│   │               │   │   │   ├── index.ts
│   │               │   │   │   └── menuItem.ts
│   │               │   │   ├── index.ts
│   │               │   │   └── pageContainer/
│   │               │   │       ├── PageContainer.tsx
│   │               │   │       └── index.ts
│   │               │   ├── lib/
│   │               │   │   └── utils.ts
│   │               │   ├── main.tsx
│   │               │   ├── pages/
│   │               │   │   ├── codesList/
│   │               │   │   │   ├── CodesList.tsx
│   │               │   │   │   ├── components/
│   │               │   │   │   │   ├── StatusAccordian.tsx
│   │               │   │   │   │   ├── index.ts
│   │               │   │   │   │   └── types.ts
│   │               │   │   │   └── index.ts
│   │               │   │   ├── findCode/
│   │               │   │   │   ├── FindCode.tsx
│   │               │   │   │   ├── components/
│   │               │   │   │   │   ├── ComboBox.tsx
│   │               │   │   │   │   └── index.ts
│   │               │   │   │   └── index.ts
│   │               │   │   ├── home/
│   │               │   │   │   ├── Home.tsx
│   │               │   │   │   ├── assets/
│   │               │   │   │   │   └── index.ts
│   │               │   │   │   ├── home.css
│   │               │   │   │   └── index.ts
│   │               │   │   ├── index.ts
│   │               │   │   └── quiz/
│   │               │   │       ├── Quiz.tsx
│   │               │   │       ├── components/
│   │               │   │       │   ├── QuestionsCard.tsx
│   │               │   │       │   └── index.ts
│   │               │   │       └── index.ts
│   │               │   ├── router/
│   │               │   │   ├── index.ts
│   │               │   │   ├── router.tsx
│   │               │   │   └── routes.ts
│   │               │   ├── services/
│   │               │   │   ├── codesList.ts
│   │               │   │   └── types.ts
│   │               │   ├── store/
│   │               │   │   └── store.ts
│   │               │   └── vite-env.d.ts
│   │               ├── tailwind.config.js
│   │               ├── tsconfig.json
│   │               ├── tsconfig.node.json
│   │               └── vite.config.ts
│   └── public/
│       ├── books/
│       │   └── .gitkeep
│       ├── cats/
│       │   └── .gitkeep
│       ├── dogs/
│       │   └── .gitkeep
│       ├── meals/
│       │   └── .gitkeep
│       ├── quotes/
│       │   └── .gitkeep
│       ├── randomjokes/
│       │   └── .gitkeep
│       ├── randomproducts/
│       │   └── .gitkeep
│       ├── randomusers/
│       │   └── .gitkeep
│       ├── stocks/
│       │   └── .gitkeep
│       └── youtube/
│           └── .gitkeep
├── nodemon.json
├── package.json
├── playwright.config.js
├── prepare.js
├── public/
│   ├── assets/
│   │   └── templates/
│   │       ├── html_response.html
│   │       └── xml_response.xml
│   ├── images/
│   │   └── .gitkeep
│   └── temp/
│       └── .gitkeep
└── src/
    ├── app.js
    ├── constants.js
    ├── controllers/
    │   ├── apps/
    │   │   ├── auth/
    │   │   │   └── user.controllers.js
    │   │   ├── chat-app/
    │   │   │   ├── chat.controllers.js
    │   │   │   └── message.controllers.js
    │   │   ├── ecommerce/
    │   │   │   ├── address.controllers.js
    │   │   │   ├── cart.controllers.js
    │   │   │   ├── category.controllers.js
    │   │   │   ├── coupon.controllers.js
    │   │   │   ├── order.controllers.js
    │   │   │   ├── product.controllers.js
    │   │   │   └── profile.controllers.js
    │   │   ├── social-media/
    │   │   │   ├── bookmark.controllers.js
    │   │   │   ├── comment.controllers.js
    │   │   │   ├── follow.controllers.js
    │   │   │   ├── like.controllers.js
    │   │   │   ├── post.controllers.js
    │   │   │   └── profile.controllers.js
    │   │   └── todo/
    │   │       └── todo.controllers.js
    │   ├── healthcheck.controllers.js
    │   ├── kitchen-sink/
    │   │   ├── cookie.controllers.js
    │   │   ├── httpmethod.controllers.js
    │   │   ├── image.controllers.js
    │   │   ├── redirect.controllers.js
    │   │   ├── requestinspection.controllers.js
    │   │   ├── responseinspection.controllers.js
    │   │   └── statuscode.controllers.js
    │   └── public/
    │       ├── book.controllers.js
    │       ├── cat.controllers.js
    │       ├── dog.controllers.js
    │       ├── meal.controllers.js
    │       ├── quote.controllers.js
    │       ├── randomjoke.controllers.js
    │       ├── randomproduct.controllers.js
    │       ├── randomuser.controllers.js
    │       ├── stock.controllers.js
    │       └── youtube.controllers.js
    ├── db/
    │   └── index.js
    ├── index.js
    ├── json/
    │   ├── books.json
    │   ├── cats.json
    │   ├── dogs.json
    │   ├── meals.json
    │   ├── nse-stocks.json
    │   ├── quotes.json
    │   ├── randomjoke.json
    │   ├── randomproduct.json
    │   ├── randomuser.json
    │   ├── status-codes.json
    │   └── youtube/
    │       ├── channel.json
    │       ├── comments.json
    │       ├── playlistitems.json
    │       ├── playlists.json
    │       └── videos.json
    ├── logger/
    │   ├── morgan.logger.js
    │   └── winston.logger.js
    ├── middlewares/
    │   ├── auth.middlewares.js
    │   ├── error.middlewares.js
    │   └── multer.middlewares.js
    ├── models/
    │   └── apps/
    │       ├── auth/
    │       │   └── user.models.js
    │       ├── chat-app/
    │       │   ├── chat.models.js
    │       │   └── message.models.js
    │       ├── ecommerce/
    │       │   ├── address.models.js
    │       │   ├── cart.models.js
    │       │   ├── category.models.js
    │       │   ├── coupon.models.js
    │       │   ├── order.models.js
    │       │   ├── product.models.js
    │       │   └── profile.models.js
    │       ├── social-media/
    │       │   ├── bookmark.models.js
    │       │   ├── comment.models.js
    │       │   ├── follow.models.js
    │       │   ├── like.models.js
    │       │   ├── post.models.js
    │       │   └── profile.models.js
    │       └── todo/
    │           └── todo.models.js
    ├── passport/
    │   └── index.js
    ├── routes/
    │   ├── apps/
    │   │   ├── auth/
    │   │   │   └── user.routes.js
    │   │   ├── chat-app/
    │   │   │   ├── chat.routes.js
    │   │   │   └── message.routes.js
    │   │   ├── ecommerce/
    │   │   │   ├── address.routes.js
    │   │   │   ├── cart.routes.js
    │   │   │   ├── category.routes.js
    │   │   │   ├── coupon.routes.js
    │   │   │   ├── order.routes.js
    │   │   │   ├── product.routes.js
    │   │   │   └── profile.routes.js
    │   │   ├── social-media/
    │   │   │   ├── bookmark.routes.js
    │   │   │   ├── comment.routes.js
    │   │   │   ├── follow.routes.js
    │   │   │   ├── like.routes.js
    │   │   │   ├── post.routes.js
    │   │   │   └── profile.routes.js
    │   │   └── todo/
    │   │       └── todo.routes.js
    │   ├── healthcheck.routes.js
    │   ├── kitchen-sink/
    │   │   ├── cookie.routes.js
    │   │   ├── httpmethod.routes.js
    │   │   ├── image.routes.js
    │   │   ├── redirect.routes.js
    │   │   ├── requestinspection.routes.js
    │   │   ├── responseinspection.routes.js
    │   │   └── statuscode.routes.js
    │   └── public/
    │       ├── book.routes.js
    │       ├── cat.routes.js
    │       ├── dog.routes.js
    │       ├── meal.routes.js
    │       ├── quote.routes.js
    │       ├── randomjoke.routes.js
    │       ├── randomproduct.routes.js
    │       ├── randomuser.routes.js
    │       ├── stock.routes.js
    │       └── youtube.routes.js
    ├── seeds/
    │   ├── _constants.js
    │   ├── chat-app.seeds.js
    │   ├── ecommerce.seeds.js
    │   ├── social-media.seeds.js
    │   ├── todo.seeds.js
    │   └── user.seeds.js
    ├── socket/
    │   └── index.js
    ├── swagger.yaml
    ├── utils/
    │   ├── ApiError.js
    │   ├── ApiResponse.js
    │   ├── asyncHandler.js
    │   ├── helpers.js
    │   └── mail.js
    └── validators/
        ├── apps/
        │   ├── auth/
        │   │   └── user.validators.js
        │   ├── chat-app/
        │   │   ├── chat.validators.js
        │   │   └── message.validators.js
        │   ├── ecommerce/
        │   │   ├── address.validators.js
        │   │   ├── cart.validators.js
        │   │   ├── category.validators.js
        │   │   ├── coupon.validators.js
        │   │   ├── order.validators.js
        │   │   ├── product.validators.js
        │   │   └── profile.validators.js
        │   ├── social-media/
        │   │   ├── comment.validators.js
        │   │   ├── post.validators.js
        │   │   └── profile.validators.js
        │   └── todo/
        │       └── todo.validators.js
        ├── common/
        │   └── mongodb.validators.js
        ├── kitchen-sink/
        │   ├── cookie.validators.js
        │   ├── redirect.validators.js
        │   ├── responseinspection.validators.js
        │   └── statuscode.validators.js
        └── validate.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-syntax-import-assertions"]
}

================================================
FILE: .commitlintrc.json
================================================
{
  "extends": ["@commitlint/config-conventional"],
  "rules": {
    "type-enum": [
      2,
      "always",
      [
        "ci",
        "chore",
        "docs",
        "feat",
        "fix",
        "perf",
        "refactor",
        "revert",
        "style",
        "assets",
        "test"
      ]
    ]
  }
}


================================================
FILE: .dockerignore
================================================
/.vscode
/node_modules

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yaml
================================================
name: 🐞 Bug report
description: Create a report to help us improve
title: "BUG: <title>"

labels:
  - bug

body:
  - type: textarea
    id: bug_description
    attributes:
      label: Describe the bug
      description: A clear and concise description of what the bug is.
    validations:
      required: true

  - type: textarea
    id: reproduce_steps
    attributes:
      label: To Reproduce
      description: Steps to reproduce the behavior.
    validations:
      required: false

  - type: textarea
    id: expected_behavior
    attributes:
      label: Expected behavior
      description: A clear and concise description of what you expected to happen.
    validations:
      required: false

  - type: textarea
    id: screenshots
    attributes:
      label: Screenshots
      description: If applicable, add screenshots to help explain your problem.

  - type: input
    id: os_info
    attributes:
      label: OS
      description: Operating System information (e.g., iOS).
      placeholder: MacOS
    validations:
      required: false
      
  - type: input
    id: version_info
    attributes:
      label: OS Version
      description: OS Version information.
      placeholder: "13.1"
    validations:
      required: false

  - type: input
    id: client_info
    attributes:
      label: Client
      description: Client information (e.g., postman, thunder client, chrome, safari).
      placeholder: Postman
    validations:
      required: false



  - type: textarea
    id: additional_context
    attributes:
      label: Additional context or Information
      description: Add any other context or any other information about the problem here.



================================================
FILE: .github/ISSUE_TEMPLATE/code_coverage.yaml
================================================
name: 🧪 Testing Contribution
description: Share details about your test coverage for contribution to FreeAPI.
title: "TESTING: <title>"

labels:
  - testing

body:
  - type: textarea
    id: test_description
    attributes:
      label: Describe the test
      description: A clear and concise description of the proposed testing suite.
    validations:
      required: true

  - type: textarea
    id: additional_info
    attributes:
      label: Additional Information
      description: Add any extra details or considerations that might be relevant such as screenshots.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
  - name: FreeAPI Discord Server
    url: https://hitesh.ai/discord
    about: Please ask and answer questions related to FreeAPI here.
  - name: Learn FreeAPI here
    url: https://www.youtube.com/playlist?list=PLRAV69dS1uWSx4erHGq8hW_GE-Eaj60r-
    about: Gain comprehensive knowledge of FreeAPI through this curated playlist.

================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yaml
================================================
name: 🌟 Feature Request
description: Suggest an enhancement, new feature or anything
title: "FEATURE: <title>"

labels:
  - enhancement

body:
  - type: textarea
    id: feature_description
    attributes:
      label: Describe the Feature
      description: A clear and concise description of the proposed feature or enhancement.
    validations:
      required: true

  - type: textarea
    id: use_case
    attributes:
      label: Use Case
      description: Provide a scenario or use case where this feature would be beneficial.
    validations:
      required: false

  - type: textarea
    id: additional_info
    attributes:
      label: Additional Information
      description: Add any extra details or considerations that might be relevant.
    validations:
      required: false

  - type: textarea
    id: suggested_tools
    attributes:
      label: Suggested Tools
      description: List any tools or technologies you suggest for implementing this feature.
    validations:
      required: false

  - type: textarea
    id: additional_context
    attributes:
      label: Additional Context or Information
      description: Add any other context or information that might be useful for understanding the feature request.


================================================
FILE: .github/ISSUE_TEMPLATE/frontend_contribution.yaml
================================================
name: 🚀 Frontend Contribution
description: Share details about your frontend application for contribution to FreeAPI.
title: "FRONTEND: <title>"

labels:
  - frontend
  - enhancement

body:
  - type: input
    id: app_title
    attributes:
      label: Frontend App Title
      description: Provide a title for your frontend application.
    validations:
      required: true

  - type: textarea
    id: overview
    attributes:
      label: Overview
      description: Briefly describe your frontend application.
    validations:
      required: true

  - type: textarea
    id: detailed_features
    attributes:
      label: Detailed Features
      description: List the features of your frontend application in detail.
    validations:
      required: true

  - type: input
    id: tech_stack
    attributes:
      label: Tech Stack Used
      description: Specify the technologies used in your frontend application (comma-separated).
      placeholder: "ReactJs, redux, tailwindCSS..."
    validations:
      required: true

  - type: input
    id: platform
    attributes:
      label: Built For Platform
      description: Specify the platform on which this application will run.
      placeholder: "web, mobile, desktop..."
    validations:
      required: true

  - type: input
    id: project_path
    attributes:
      label: Project Path
      description: Provide the path to your project within the FreeAPI project's `examples` folder.
      placeholder: E.g. $ROOT_FOLDER/examples/apps/social-media/web/react-redux-tailwind/<your_project_folders>
    validations:
      required: true


================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# Logs
logs

/tmp
/.vscode
/.idea

# ignore the image files uploaded in the public/images folder
/public/images/*
/public/temp/*

# except .gitkeep to push empty folder to the git repo
!/public/images/.gitkeep
!/public/temp/.gitkeep

NOTES.md
.DS_Store

# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/


================================================
FILE: .husky/commit-msg
================================================
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx --no-install commitlint --edit


================================================
FILE: .husky/pre-commit
================================================
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged --allow-empty


================================================
FILE: .lintstagedrc
================================================
{
  "**/*.{js,json}": ["prettier --write"]
}


================================================
FILE: .prettierignore
================================================
/.vscode
/node_modules
./dist

*.yml
*.yaml

*.env
.env
.env.*

================================================
FILE: .prettierrc
================================================
{
  "singleQuote": false,
  "bracketSpacing": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "semi": true
}


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to FreeAPI

Thank you for your interest in contributing to FreeAPI! We welcome contributions from the software community to help improve and enhance this project.

By contributing, you can help make FreeAPI a more valuable resource for developers and contribute to the growth of the open-source community.

## Table of Contents

1. [📙 How to Contribute](#how-to-contribute)
2. [䷫ Commit Message Format](#commit-message-format)
3. [👨🏻‍⚖️ Guidelines for Contribution](#contribution-guidelines)
4. [🚀 Contribute as a frontend developer](#frontend-contributor)

## How to Contribute <a name="how-to-contribute"></a>

To contribute to FreeAPI, please follow these guidelines:

1. Fork the repository on GitHub.
2. Clone your forked repository to your local machine.
3. Create a new branch for your feature or bug fix: `git checkout -b feat/your-feature-name` or `git checkout -b fix/your-bug-fix-name` and make your changes.
4. Run all the tests 🧪 before committing the changes and make sure all tests are passed.
5. After all tests are passed, commit your changes with a descriptive messages: `git commit -am 'add your commit message'`.
6. Push your changes to your forked repository: `git push origin feat/your-feature-name`.
7. Submit a pull request to the main repository.

## Commit Message Format <a name="commit-message-format"></a>

We follow the conventional commit message format to provide a clear and standardized history of our project's changes. Each commit message should consist of a type and a descriptive message.

| Type     | Heading  | Rule                                       | Description                                                                       |
| -------- | -------- | ------------------------------------------ | --------------------------------------------------------------------------------- |
| ci       | CI       | Continuous Integration                     | Changes related to continuous integration.                                        |
| chore    | Chore    | Maintenance tasks                          | Other changes that don't affect production.                                       |
| docs     | Docs     | Documentation                              | Changes related to documentation.                                                 |
| feat     | Feature  | New Feature                                | New feature implementations or additions.                                         |
| fix      | Fix      | Bug Fixes                                  | Bug fixes or corrections.                                                         |
| perf     | Perf     | Performance Improvements                   | Performance-related improvements.                                                 |
| refactor | Refactor | Code Refactoring                           | Code changes that don't fix bugs or add features, but improve the code structure. |
| revert   | Revert   | Revert Previous Commits                    | Reverting previous commits.                                                       |
| style    | Style    | Code Formatting or Style                   | Changes related to code formatting or style.                                      |
| assets   | Assets   | Add or Update Assets (e.g., images, files) | Changes related to adding or updating assets, such as images or other files.      |

### Format

The commit message should start with the type, followed by a colon and a space, and then the descriptive message in present tense.

Example:

- feat: add user authentication feature
- fix: correct typo in README

Please adhere to this format when making commits. This will help us maintain a clean and organized commit history.

## Guidelines for Contribution <a name="contribution-guidelines"></a>

Here's a guide on how you can effectively contribute to our API hub:

1. Pull Requests for Readme Updates: Please refrain from sending pull requests solely for updating the project's readme file. While we appreciate the importance of clear and concise documentation, we prefer to focus on substantial code contributions and feature enhancements.

2. Grammar Updates: Our team values effective communication, but we're not grammar sticklers. You don't need to send pull requests solely for grammar fixes or minor language improvements. Instead, concentrate on the core functionalities and features of the project.

3. Avoid Updating Existing Public APIs: To maintain stability and consistency, we discourage direct updates to existing public APIs within the API hub. These APIs have been thoroughly tested and approved. However, if you encounter any bugs or issues, we encourage you to open an issue on our project's issue tracker to notify us.

4. Build New Project APIs: We encourage you to explore your creativity and contribute by building complete project APIs. These APIs should provide comprehensive solutions that can assist developers in constructing complex projects to showcase their skills and abilities. Your contributions in this area will greatly benefit the community.

5. Draft a Proposal and Discuss on Discord: Before diving into your project, we recommend drafting a proposal. This can include a mind map or outline of the API you intend to build and its potential benefits. Join our Discord community, where you can share your proposal, discuss ideas, and gather feedback from fellow contributors. Engaging in these discussions will enhance your backend portfolio and help shape the future direction of the project.

We appreciate your enthusiasm and look forward to your valuable contributions to our open source API hub project.

Together, we can foster a collaborative environment and make a significant impact in the API integration landscape.

## Contribute as a frontend developer <a name="frontend-contributor"></a>

Are you a Frontend developer looking to create elegant mobile/web apps which consumes FreeAPIs? Then follow this [Frontend Contribution guide](https://github.com/hiteshchoudhary/apihub/blob/main/CONTRIBUTING_FRONTEND.md) and contribute as a frontend developer


================================================
FILE: CONTRIBUTING_CODE_COVERAGE.md
================================================
# FreeAPI Testing Contribution Guide

Thank you for your interest in contributing to the FreeAPI project to help us deliver our APIs that are battlefield tested. To ensure reliability & stability for our end users, we utilize Playwright, a powerful testing framework to automate testing across all endpoints.

### Why Playwright?

After exploring our open-source community options such as Jest, Jasmine & Playwright. We decided to move forward with the playwright as it facilitates automated testing, offers cross-browser support, rich enough API with familiar syntax.

## ⚠️ Important Note:

### Before starting your contribution

- create an issue stating which module you will be working on
- in a given module if tests exist, we do not welcome them as long as it is a logical fix
- test coverage for example frontend apps are not our top priority

**IMPORTANT: Contributor must create an issue with [Testing Contribution](https://github.com/hiteshchoudhary/apihub/issues/new?assignees=&labels=testing&projects=&template=code_coverage.yaml&title=TESTING%3A+%3Ctitle%3E) issue template.**

This ensures coordination and prevents duplicated efforts.

## Table of Contents

1. [🏁 Getting Started](#getting-started)
2. [👆🏻 Choosing a Module](#choosing-a-module)
3. [🗂️ Folder Structure](#folder-structure-main)
4. [📙 Coding Standards](#coding-standards)
5. [📝 Dependency Management](#dependency-management)
6. [📨 Submitting Your Contribution](#submitting-your-contribution)

## Getting Started <a name="getting-started"></a>

### Fork the Repository

Start by forking the FreeAPI project repository to your GitHub account.

### Clone Your Fork

Clone your fork of the repository to your local machine.

```bash
git clone https://github.com/<your_username>/apihub.git
cd apihub
```

### Install Dependencies

Make sure you have the necessary dependencies of FreeAPI installed for the frontend framework or library you plan to use.

Follow this [README.md section](https://github.com/hiteshchoudhary/apihub/blob/main/README.md#-installation) to know more about setting up the FreeAPI environment

## Choosing a Module <a name="choosing-a-module"></a>

Decide which module you want to contribute to. Browse the `/apps`, `/public`, or `/kitchen-sink` modules to explore the available modules and APIs. Read the following section carefully to understand the folder structure you need to follow to increase your chances of getting your PR approved.

## Folder Structure <a name="folder-structure-main"></a>

Follow the specified folder structure for your frontend application (**The folder names must not follow the camel casing to keep things consistent.** _Your actual project code folders may have camel casing_):

```
ROOT_FOLDER/e2e/{module}/
```

See the following examples with context for the above structure:

## Example: Todo endpoint testing

Imagine you want to test the todo endpoint that is part of `/apps` module of the FreeAPI project. To keep a consistent folder structure for backtracking name your files with name identifier, but with an extension of `.test.js`.

### Folder Structure:

```
$ROOT_FOLDER/e2e/{package}/{module}/{file-indicator}.test.js
```

## Explanation for the examples:

- `ROOT_FOLDER`: Refers to the root directory of the FreeAPI project.

- `e2e`: This directory is designated for including test cases.

- `{package}`: The directory contains typical of a Node.js application: `app.js` initializes the app, `controllers` handle requests, `models` define data structures, `routes` map endpoints, `utils` provide utilities, and others manage logging, authentication, and database interactions.

- `{module}`: `apps` or `public` or `kitchen-sink`: Denotes the chosen module (`/apps` for complex apps, `/public` for public APIs, `/kitchen-sink` for backend-related static APIs. These folders are already created officially).

- `{file-indicator}`: This is the actual file name indicator that helps to identify for which file you are writing test cases for example: `todo.test.js`

By following this standardized folder structure, contributors can easily organize their front-end projects, making it convenient for others to explore, understand, and replicate the implementation.

## Coding Standards <a name="coding-standards"></a>

Adhere to the coding standards of the playwright framework. Additionally, consider the following guidelines:

- Use clear descriptive test suite & block names
- Follow best practices for unit, integration & end-to-end testing
- Ensure your code is well-documented by comments wherever necessary
- Make sure to add both positive & negative test cases

## Dependency Management <a name="dependency-management"></a>

Ideally, we do not encourage you to include a new package. Confine your code practices within the available dependencies to avoid overheads. Please state with a clear explanation with examples if you add anything new.

## Submitting Your Contribution <a name="submitting-your-contribution"></a>

Click [here](https://github.com/hiteshchoudhary/apihub/blob/main/CONTRIBUTING.md) for a detailed contribution guide on submitting a PR.

Thank you for your contribution to FreeAPI! Your dedication helps make our APIs more accessible and valuable to the community. If you have any questions or need assistance, feel free to reach out to our [Discord](https://hitesh.ai/discord).

Thank you for being part of the FreeAPI community and contributing to the project! We look forward to featuring your fantastic work. 🌟

Happy coding! 🚀


================================================
FILE: CONTRIBUTING_FRONTEND.md
================================================
# FreeAPI Frontend Contribution Guide

Thank you for your interest in contributing to the FreeAPI project by creating frontend applications! Your efforts play a crucial role in enhancing the user experience and expanding the reach of our APIs. Please follow this guide to ensure a smooth and collaborative contribution process.

## ⚠️ Important Note:

### Before starting your contribution

- create an issue stating the app you will be working on
- the technology stack you plan to use
- the platform you intend to target.
- describe your application in detail

**IMPORTANT: Contributor must create an issue with [Frontend Contribution](https://github.com/hiteshchoudhary/apihub/issues/new?assignees=&labels=frontend%2Cenhancement&projects=&template=frontend_contribution.yaml&title=FRONTEND%3A+%3Ctitle%3E) issue template.**

This ensures coordination and prevents duplicated efforts.

## Table of Contents

1. [🏁 Getting Started](#getting-started)
2. [👆🏻 Choosing a Module](#choosing-a-module)
3. [🗂️ Folder Structure](#folder-structure-main)
4. [📙 Coding Standards](#coding-standards)
5. [📝 Dependency Management](#dependency-management)
6. [🧪 Testing (optional)](#testing)
7. [📨 Submitting Your Contribution](#submitting-your-contribution)
8. [🌟 Featured Projects Opportunity on FreeAPI](#featured-projects)
9. [🌟 How To Get Featured](#get-featured)

## Getting Started <a name="getting-started"></a>

### Fork the Repository

Start by forking the FreeAPI project repository to your GitHub account.

### Clone Your Fork

Clone your fork of the repository to your local machine.

```bash
git clone https://github.com/<your_username>/apihub.git
cd apihub
```

### Install Dependencies

Make sure you have the necessary dependencies of FreeAPI installed for the frontend framework or library you plan to use.

Follow this [README.md section](https://github.com/hiteshchoudhary/apihub/blob/main/README.md#-installation) to know more about setting up the FreeAPI environment

## Choosing a Module <a name="choosing-a-module"></a>

Decide which module you want to contribute to. Browse the `/apps`, `/public`, or `/kitchen-sink` modules to explore the available modules and APIs. Read the following section carefully to understand the folder structure you need to follow to increase chances to get your PR approved.

## Folder Structure <a name="folder-structure-main"></a>

Follow the specified folder structure for your frontend application (**The folder names must not follow the camel casing to keep things consistent.** _Your actual project code folders may have camel casing_):

```
ROOT_FOLDER/examples/{module}/{app-name}/{platform}/{frontend-tech-used}/{project-code}
```

See the following examples with context for above structure:

## Example 1: Social Media Web App

Imagine you want to create a web application for the `social-media` project within the `/apps` module of the FreeAPI project. You've decided to use React.js for the frontend, manage state with Redux, and style the app with Tailwind CSS. Your project folder name will be a unique identifier for your application because we are not allowing same application to be built using same tech stack.

### Folder Structure:

```
$ROOT_FOLDER/examples/apps/social-media/web/react-redux-tailwind/<your_project_folders>
```

## Example 2: YouTube Mobile App

Suppose you are interested in building a mobile application that consumes the YouTube API from the `/public` folder of the FreeAPI project. For this, you've chosen Flutter as your framework, and you'll be using Riverpod for state management. Again, your project folder name will be a unique identifier for your application because we are not allowing same application to be built using same tech stack.

### Folder Structure:

```bash
$ROOT_FOLDER/examples/public/youtube/mobile/flutter-riverpod/<your_project_folders>
```

## Example 3: Status Code Lookup App

You want to contribute a frontend application to the `/kitchen-sink` module that allows users to input a numerical HTTP status code. The app will then provide details about that status code, such as its purpose and common usage with elegant UI.

## Folder Structure:

```bash
$ROOT_FOLDER/examples/kitchen-sink/statuscodes/web/react-tailwind/<your_project_folders>
```

## Explanation for the examples:

- `ROOT_FOLDER:` Refers to the root directory of the FreeAPI project.

- `examples:` This directory is designated for frontend examples.

- `{module} - apps or public or kitchen-sink:` Denotes the chosen module (`/apps` for complex apps, `/public` for public APIs, `/kitchen-sink` for backend-related static APIs. These folders are already created officially).

- `{app_name} - social-media or youtube or statuscode:` Specifies the name of the chosen app or API within the selected module. This folder is also created by default officially.

- `{platform} - web or mobile or desktop:` Defines the platform for which the frontend is developed (web or mobile or desktop etc).

- `{frontend-tech-used} - react-redux-tailwind or flutter-provider:` Indicates the frontend technology stack used, including the framework, UI-lib and state management tool (at least one tech tool name must be there).

- `<your_project_folders>:` Represents the actual project folders that will be coding.

By following this standardized folder structure, contributors can easily organize their frontend projects, making it convenient for others to explore, understand, and replicate the implementation.

## Coding Standards <a name="coding-standards"></a>

Adhere to the coding standards of the chosen frontend technology and framework. Additionally, consider the following guidelines:

- Use clear and descriptive variable and function names.
- Follow best practices for state management, component structure, and code organization.
- Ensure your code is well-documented by comments wherever necessary.
- Try to use type safe languages like TypeScript over JavaScript to code the frontend
- **Include comprehensive README.md file for each project on how to do installation and setup for the respective apps**

## Dependency Management <a name="dependency-management"></a>

List all major dependencies/tech tools used in a clear and organized manner in your project README.md. Include version numbers to ensure compatibility.

## Testing (optional) <a name="testing"></a>

Write tests for your frontend application to ensure its functionality. Include instructions on how to run the tests.

## Submitting Your Contribution <a name="submitting-your-contribution"></a>

Click [here](https://github.com/hiteshchoudhary/apihub/blob/main/CONTRIBUTING.md) for detailed contribution guide on submitting a PR.

Thank you for your contribution to FreeAPI! Your dedication helps make our APIs more accessible and valuable to the community. If you have any questions or need assistance, feel free to reach out to our [Discord](https://hitesh.ai/discord).

## 🌟 Featured Projects Opportunity on FreeAPI <a name="featured-projects"></a>

We value the contributions of our community members, and we want to showcase your work! As part of our effort to highlight the creativity and diversity of the FreeAPI project, we are introducing a Featured Projects section on the official [FreeAPI](https://freeapi.app) site (under development).

## How to Get Featured <a name="get-featured"></a>

1. **Self-Host the FreeAPI Backend:**

   - Ensure that you have set up and are self-hosting the FreeAPI backend on your server. Detailed instructions can be found in the [README.md Railway one click deploy section](https://github.com/hiteshchoudhary/apihub/blob/main/README.md#-using-railway-one-click-deploy). _(NOTE: You can deploy this app on server that you are comfortable with. Just make sure it is deployed and your deployed frontend can consume it's apis)_

2. **Consume FreeAPI Backend APIs in Your Frontend:**

   - In your frontend project, make sure you are consuming the relevant FreeAPI backend APIs from the deployed backend server. This demonstrates the end-to-end functionality of your application.

3. **Deploy Your Frontend:**

   - Deploy your frontend application, and ensure it is accessible via a public URL.

4. **Include Deployed Link in README.md:**
   - Add the deployed link to your frontend application at the top of the README.md file in your project code. This link will serve as the entry point for us to review and feature your project.

### Example README Section:

```markdown
<!-- other README.md content -->
<!-- make sure to keep this link at the top to make it visible -->

## Deployed Link

Visit my app: [https://my-social-media-app.example.com](https://my-social-media-app.example.com)

 <!-- other README.md content -->
```

### Why to get featured?

1. **Contribution in Open Source:**

   - Gain recognition and celebrate contributions within the FreeAPI community.
   - Enhance your portfolio with real-world open source projects.

2. **Deployed Project:**

   - Gain hands-on experience with real-world deployment challenges.
   - Enhance your portfolio with a deployed and functional application.

3. **Showcasing Your Work:**

   - Increase visibility by being featured on the official FreeAPI website.
   - Receive recognition from the FreeAPI community.

4. **Networking Opportunities:**

   - Connect with like-minded individuals within the FreeAPI community.
   - Showcase your skills to potential collaborators, mentors, or employers.

5. **Beta Stage Advantage:**

   - Gain early recognition as an early adopter and contributor.
   - Influence the future development of the Featured Projects feature.

6. **Skill Showcase:**

   - Showcase proficiency in both backend consumption and frontend development.
   - Highlight your preferred frontend tech stack.

### What Happens Next:

- **Beta Stage:** While this feature is in beta, our team will be actively monitoring deployed links mentioned in README.md files of frontend example projects.

- **Official Rollout:** Once the Featured Projects page is officially launched on [FreeAPI](https://freeapi.app), we will review and select projects from the submitted links to showcase. So, you can start deploying your apps.

- **Notification:** If your project is selected, we will notify you and include your project in the Featured Projects section on [FreeAPI](https://freeapi.app).

### Important Note:

- Projects with deployed links mentioned at the top of the README.md file have a higher chance of being featured.
- This feature is in beta, and we appreciate your early contributions to help shape the future of FreeAPI. The more links we get the sooner this section will get up and running.

Thank you for being part of the FreeAPI community and contributing to the project! We look forward to featuring your fantastic work. 🌟

Happy coding! 🚀


================================================
FILE: Dockerfile
================================================
FROM node:20.13.1-alpine

RUN mkdir -p /usr/src/freeapi && chown -R node:node /usr/src/freeapi

WORKDIR /usr/src/freeapi

# Copy package json and yarn lock only to optimise the image building
COPY package.json yarn.lock ./

# copy prepare.js prior. It will be executed after package installation and before ROOT dir is cloned
COPY prepare.js ./

USER node

RUN yarn install --pure-lockfile

COPY --chown=node:node . .

EXPOSE 8080

CMD [ "npm", "start" ]

================================================
FILE: LICENSE.md
================================================
MIT License

FreeAPI

Copyright (c) 2023 Hitesh Choudhary

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# FreeAPI.app

## Problem

We are trying to build a single source API hub that can be used to learn api handling in any programming language. Users can build their front end portfolio in web and mobile apps using this api hub.

# What is FreeAPI.app

The FreeAPI project is an innovative and community-driven initiative aimed at providing developers with free and accessible APIs for their projects.

The project focuses on delivering a wide range of APIs that cater to various domains and functionalities, enabling developers to seamlessly integrate these APIs into their applications.

Key highlights of the FreeAPI project include:

1. **Accessibility:** The FreeAPI project is committed to eliminating barriers by providing free access to its collection of APIs.
   Developers can leverage these APIs without any cost limitations, allowing them to experiment, learn, and build innovative applications.

2. **Diverse API Collection:** The project offers a diverse and comprehensive collection of APIs that span across different industries, domains, and functionalities.
   Whether you require social media integrations, payment gateways, machine learning algorithms, or IoT device connectivity, the FreeAPI project has you covered.

3. **Simplified Integration:** The FreeAPI project understands the challenges developers face when integrating APIs into their applications. To address this, the project provides clear documentation, code samples, and SDKs, simplifying the integration process and reducing development time and effort.

4. **Community-Driven Development:** The project fosters a vibrant and collaborative community of developers. Contributors are encouraged to share their knowledge, engage in discussions, and collaborate on API-related projects. This collective effort ensures the continuous improvement and reliability of the APIs offered by the FreeAPI project.

5. **Learning and Skill Development:** The FreeAPI project aims to empower developers by providing a platform for learning and skill development. Through access to various APIs and educational resources, developers can enhance their understanding of API integration, expand their knowledge, and showcase their expertise through building complete projects.

Overall, the FreeAPI project is a valuable resource for developers seeking accessible and diverse APIs.

By fostering a supportive community, the project empowers developers to learn, create, and innovate, ultimately contributing to the growth and advancement of the API integration landscape.

## Features:

Introducing our groundbreaking open source API hub project, a dynamic platform designed to revolutionize the way developers interact with APIs.

With an emphasis on openness, accessibility, and learning, our API hub empowers developers of all levels to explore, experiment, and grow their skills in API integration.

Highlights:

1. **Open Source:** Our API hub is built on the principles of open source, ensuring transparency, collaboration, and community-driven development. This means that the source code is freely available, allowing developers to customize, extend, and contribute to the project.

2. **Free to Use:** We firmly believe in removing barriers to entry, which is why our API hub is completely free to use. Whether you're a seasoned developer or just starting your coding journey, you can leverage our platform without any cost limitations.

3. **Local or Deployment**: Flexibility is at the core of our API hub. You have the option to use it locally, running on your own machine, or deploy it to a server, making it accessible to others. This versatility ensures that you can adapt the platform to your specific development environment.

4. **Learning Resource**: Our API hub is designed as a comprehensive learning resource, offering a wealth of educational materials, tutorials, and documentation. Whether you're a beginner or seeking to expand your API knowledge, our platform provides the resources you need to learn and improve.

5. **Custom Endpoints for Beginners**: For developers at the beginner level, our API hub offers custom endpoints that provide a hands-on experience in handling API responses. These beginner-friendly APIs allow you to practice and familiarize yourself with the basics of working with APIs.

6. **Advanced APIs for Portfolio Building**: In addition to beginner-level endpoints, our API hub also provides advanced APIs to challenge and stretch your skills. These APIs enable you to tackle more complex integration scenarios, helping you build a robust portfolio of projects to showcase your expertise.

By combining open source principles, accessibility, and a focus on learning, our API hub project paves the way for developers to thrive in the world of API integration. Join our vibrant community and embark on an exciting journey of discovery, growth, and innovation.

# ⚠️ Important Note: Avoiding Data Loss and Self-Hosting

# Background:

Our open-source project is currently hosted on a remote server, where we are forced to reset the entire server, **including the file system and MongoDB database**, every **2 hours** to avoid incurring additional costs.

This process results in the **deletion of all image/static files and a reset of the entire database on the server.**

## What does this mean for you?

**Data Loss:**
Any changes made during the 2-hour interval (on the remote server), including uploaded images and user data, will be lost and unrecoverable.

**Service Interruption:**
The server reset might disrupt your development and testing processes for a certain duration while the server is rebooting (for 1-2 minutes).

## Recommended Solutions:

**Local API Usage:**
For development and testing purposes, we strongly recommend using the API locally on your machine by **cloning the project**.

This ensures that your work is not affected by the server resets and allows you to maintain a stable development environment on your local machine.

**Self-Hosting on Railway _(recommended for personal projects)_:**
To self-host the FreeAPI.app application, you can take advantage of a pre-built template that is readily available.
[Click here for detailed docs](https://github.com/hiteshchoudhary/apihub/#-using-railway-one-click-deploy)

# 🏁 Installation

### 📦 Using Docker (recommended)

To run the FreeAPI project, follow these steps:

1. Install [Docker](https://www.docker.com/) on your machine.
2. Clone the project repository.
3. Navigate to the project directory.
4. Create `.env` file in the root folder and copy paste the content of `.env.sample`, and add necessary credentials.
5. Run the Docker Compose command:

```bash
docker-compose up --build --attach backend

# --build: Rebuild the image and run the containers
# --attach: only show logs of Node app container and not mongodb
```

6. Access the project APIs at the specified endpoints.

### 💻 Running locally

To run the FreeAPI project locally, follow these steps:

1. Install [Yarn](https://yarnpkg.com/), [NodeJs](https://www.nodejs.org/), [MongoDB](https://www.mongodb.com) and [MongoDB Compass (optional)](https://www.mongodb.com/products/compass) on your machine.
2. Clone the project repository.
3. Navigate to the project directory.
4. Create `.env` file in the root folder and copy paste the content of `.env.sample`, and add necessary credentials.
5. Install the packages:

```bash
yarn install
```

6. Run the project:

```bash
yarn start
```

7. Access the project APIs at the specified endpoints.

### 🚄 Using Railway (One-click Deploy)

To self-host the FreeAPI.app application, you can take advantage of a pre-built template that is readily available.

[![Deploy FreeAPI.app](https://railway.app/button.svg)](https://railway.app/template/B2f7Hq)

1. Click the button above to visit railway.app.

2. Click on the **Deploy Now** button.

3. (Optional) Sign in with GitHub to deploy.

4. Fill in the Repository details:

   - Specify the repo name (e.g., freeapi-app).
   - Checkmark for Public/Private repository.

5. For Environment variables, we have provided some default values in the `ENV` to reduce the burden, but some parameters are mandatory:

   - `PORT`: Do not change the value, let it be set to 8080 to view the swagger docs after deployment.
   - `MONGODB_URI`: Provide the MongoDB Atlas database URL. An example is prefilled for you, edit/update it to continue.
   - `NODE_ENV`: Default set to 'development' to view the logs. You may choose to change it to 'production' (make sure to add exact same word) to hide them.
   - `EXPRESS_SESSION_SECRET`: It is advised to change the default value to your own secret value.
   - `ACCESS_TOKEN_SECRET`: It is advised to change the default value to your own secret value.
   - `ACCESS_TOKEN_EXPIRY`: Set to 1 day as default.
   - `REFRESH_TOKEN_SECRET`: It is advised to change the default value to your own secret value.
   - `REFRESH_TOKEN_EXPIRY`: Set to 10 days as default.
   - `FREEAPI_HOST_URL`: Set it as generated railway url.

6. Once you fill in the required environment parameters, if you choose to add others such as PayPal, Google, and Razorpay, please proceed to mention your credentials in the form.

7. Click on the **Deploy** button to trigger the first build.
   - Monitor the server logs; if you come across any deployment problems, feel free to raise an issue for our team to look into.

Note: Once the application is deployed, please wait for 3-5 minutes for the swagger docs to be available.

# 🧪 Testing

To ensure reliability & stability for our end users, we utilize Playwright, a powerful testing framework to automate testing across all endpoints.

### 💻 Run the Test Server

Make sure to add `MONGO_MEMORY_SERVER_PORT=10000` (mongodb port for e2e testing) in your `.env` file.

```bash
yarn start:test-server
```

### 🧪 Run Tests

```bash
yarn test:playwright
```

This will generate a Playwright report. To view this report run the following command

```bash
yarn playwright show-report
```

Make sure all the test cases are passed whenever you make any changes.

# How to contribute - Guidelines

## ⚡️ Contribute in core FreeAPI codebase:

We welcome your interest in contributing to our open source project!

To contribute to FreeAPI, please follow these steps:

1. Fork the repository.
2. Create a new branch for your feature or bug fix: `git checkout -b feat/your-feature-name` or `git checkout -b fix/your-bug-fix-name` and make your changes.
3. Run all the tests 🧪 before committing the changes and make sure all tests are passed.
4. After all tests are passed, commit your changes with a descriptive messages: `git commit -am 'add your commit message'`
5. For more details on the commit format and other guidelines, please refer to the [Contributor Guidelines](./CONTRIBUTING.md).
6. Push your changes to your forked repository: `git push origin feat/your-feature-name`.
7. Submit a pull request to the main repository, explaining the changes you've made and providing any necessary details.

Here's a guide on how you can effectively contribute to our API hub:

1. Pull Requests for Readme Updates: Please refrain from sending pull requests solely for updating the project's readme file. While we appreciate the importance of clear and concise documentation, we prefer to focus on substantial code contributions and feature enhancements.

2. Grammar Updates: Our team values effective communication, but we're not grammar sticklers. You don't need to send pull requests solely for grammar fixes or minor language improvements. Instead, concentrate on the core functionalities and features of the project.

3. Avoid Updating Existing Public APIs: To maintain stability and consistency, we discourage direct updates to existing public APIs within the API hub. These APIs have been thoroughly tested and approved. However, if you encounter any bugs or issues, we encourage you to open an issue on our project's issue tracker to notify us.

4. Build New Project APIs: We encourage you to explore your creativity and contribute by building complete project APIs. These APIs should provide comprehensive solutions that can assist developers in constructing complex projects to showcase their skills and abilities. Your contributions in this area will greatly benefit the community.

5. Draft a Proposal and Discuss on Discord: Before diving into your project, we recommend drafting a proposal. This can include a mind map or outline of the API you intend to build and its potential benefits. Join our Discord community, where you can share your proposal, discuss ideas, and gather feedback from fellow contributors. Engaging in these discussions will enhance your backend portfolio and help shape the future direction of the project.

We appreciate your enthusiasm and look forward to your valuable contributions to our open source API hub project.

Together, we can foster a collaborative environment and make a significant impact in the API integration landscape.

Click [here](https://github.com/hiteshchoudhary/apihub/blob/main/CONTRIBUTING.md) for detailed contribution guide.

## 🚀 Contribute by creating frontend application:

Thank you for your interest in contributing to the FreeAPI project by creating frontend applications consuming FreeAPIs! Your efforts play a crucial role in enhancing the user experience and expanding the reach of our APIs. Please follow this guide to ensure a smooth and collaborative contribution process.

Click [here](https://github.com/hiteshchoudhary/apihub/blob/main/CONTRIBUTING_FRONTEND.md) for detailed contribution guide for Frontend Developers 🚀!

## 🧪 Contribute in testing suite

Thank you for your interest in contributing to the FreeAPI project to increase code coverage of our API service that helps us to ship robust endpoints that are battlefield tested. Please follow this guide to ensure a smooth and collaborative contribution process.

Click [here](https://github.com/hiteshchoudhary/apihub/blob/main/CONTRIBUTING_CODE_COVERAGE.md) for detailed contribution guide for increasing code coverage.

# 📜 Swagger Docs

[Swagger Docs](https://api.freeapi.app): https://api.freeapi.app

NOTE: Swagger docs are auto generated from the `swagger.yaml` file. While running the project locally, make sure you change the url to `http://localhost:<port_from_.env>/api/v1` in the swagger docs `servers/url` field.


================================================
FILE: docker-compose.prod.yml
================================================
version: '3.8'

services:
  backend:
    image: freeapi-server
    build: .
    ports:
      - 8080:8080
    volumes:
      - ./:/usr/src/freeapi
      - /usr/src/freeapi/node_modules
    env_file:
      - ./.env
    depends_on:
      - mongodb
    networks:
      - freeapi-internal
  
  mongodb:
    image: mongo
    container_name: mongodb
    volumes:
      - data:/data/db
    networks:
      - freeapi-internal

networks:
  freeapi-internal:

volumes:
  data:


================================================
FILE: docker-compose.yml
================================================
version: '3.8'

services:
  backend:
    image: freeapi-server
    build: .
    ports:
      - 8080:8080
    volumes:
      - ./:/usr/src/freeapi
      - /usr/src/freeapi/node_modules
    env_file:
      - ./.env
    depends_on:
      - mongodb
  mongodb:
    image: mongo
    container_name: mongodb
    volumes:
      - data:/data/db
    ports:
      - 27017:27017

volumes:
  data:

================================================
FILE: e2e/common.js
================================================
import dotenv from "dotenv";

dotenv.config({
  path: "../.env",
});

export const URL = `http://localhost:${process.env.PORT || 8080}`;

export const getApiContext = async (playwright) =>
  playwright.request.newContext({
    baseURL: URL,
  });


================================================
FILE: e2e/db.js
================================================
import mongoose, { mongo } from "mongoose";
import { MongoMemoryServer } from "mongodb-memory-server";

const MONGO_MEMORY_SERVER_PORT = process.env.MONGO_MEMORY_SERVER_PORT || 10000;
const MONGODB_URL = `mongodb://127.0.0.1:${MONGO_MEMORY_SERVER_PORT}/`;

let mongoServer = null;
let dbInstance = undefined;

const connectDB = async () => {
  try {
    await mongoose.disconnect();
    mongoServer = await MongoMemoryServer.create({
      instance: {
        port: +MONGO_MEMORY_SERVER_PORT,
      },
    });
    dbInstance = await mongoose.connect(MONGODB_URL);
  } catch (error) {
    console.error("Mongo db connect error: ", error);
    process.exit(1);
  }
};
export const clearDB = async (collectionName = null) => {
  if (!dbInstance) {
    dbInstance = await mongoose.connect(MONGODB_URL);
  }
  const connection = mongoose.connection;
  if (collectionName) {
    await connection.db.collection(collectionName).deleteMany({});
  } else {
    const collections = await connection.db.listCollections().toArray();
    const collectionNames = collections.map((col) => col.name);
    for (let name of collectionNames) {
      await connection.db.collection(name).deleteMany({});
    }
  }
};

export default connectDB;


================================================
FILE: e2e/routes/apps/todo.test.js
================================================
import { test, expect } from "@playwright/test";
import { getApiContext } from "../../common.js";
import { clearDB } from "../../db.js";
let apiContext;

let todoId = null;

test.describe("Todo App", () => {
  test.beforeAll(async ({ playwright }) => {
    apiContext = await getApiContext(playwright);
    await clearDB();
  });
  test.afterAll(async ({}) => {
    await apiContext.dispose();
  });

  test.describe("GET:/api/v1/todos - Get All Todos", () => {
    test("should return all todos", async () => {
      const res = await apiContext.get(`/api/v1/todos`);
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.length).toEqual(0);
    });
  });

  test.describe("POST:/api/v1/todos - Create Todo", () => {
    test("should create todo with valid data", async () => {
      const todo = {
        title: "test-todo-title",
        description: "test-todo-description",
      };
      const res = await apiContext.post(`/api/v1/todos`, {
        data: todo,
      });
      const json = await res.json();
      expect(res.status()).toEqual(201);
      expect(json.statusCode).toEqual(201);
      expect(json.data).toMatchObject(todo);
      todoId = json.data._id;
    });

    test("should return a 422 with title error when `title` is not provided", async () => {
      const todo = {};
      const res = await apiContext.post(`/api/v1/todos`, {
        data: todo,
      });
      const json = await res.json();
      expect(res.status()).toEqual(422);
      expect(json.statusCode).toEqual(422);
      expect(json.errors).toContainEqual(
        expect.objectContaining({ title: expect.anything() })
      );
    });

    test("should return a 422 with title and description error when `title` and `description` is empty", async () => {
      const todo = { title: "", description: "" };
      const res = await apiContext.post(`/api/v1/todos`, {
        data: todo,
      });
      const json = await res.json();
      expect(res.status()).toEqual(422);
      expect(json.statusCode).toEqual(422);
      expect(json.errors).toContainEqual(
        expect.objectContaining({ title: expect.anything() })
      );
      expect(json.errors).toContainEqual(
        expect.objectContaining({ description: expect.anything() })
      );
    });
  });

  test.describe("PATCH:/api/v1/todos/:id - Update Todo", () => {
    const todo = {
      title: "update-test-todo-title",
      description: "update-test-todo-description",
    };

    test("should update todo with valid data", async () => {
      const res = await apiContext.patch(`/api/v1/todos/${todoId}`, {
        data: todo,
      });
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.statusCode).toEqual(200);
      expect(json.data).toMatchObject(todo);
    });

    test("should return a 422 with title and description error when `title` and `description` is empty", async () => {
      const todo = { title: "", description: "" };
      const res = await apiContext.patch(`/api/v1/todos/${todoId}`, {
        data: todo,
      });
      const json = await res.json();
      expect(res.status()).toEqual(422);
      expect(json.statusCode).toEqual(422);
      expect(json.errors).toContainEqual(
        expect.objectContaining({ title: expect.anything() })
      );
      expect(json.errors).toContainEqual(
        expect.objectContaining({ description: expect.anything() })
      );
    });
  });

  test.describe("PATCH:/api/v1/todos/toggle/status/:id - Toggle todo status", () => {
    test("should toggle todo status", async () => {
      const res = await apiContext.patch(
        `/api/v1/todos/toggle/status/${todoId}`
      );
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.statusCode).toEqual(res.status());
      expect(json.data.isComplete).toBeTruthy();
    });
  });

  test.describe("GET:/api/v1/todos - Get All Todos", () => {
    test("should return todo when valid id passed", async () => {
      const res = await apiContext.get(`/api/v1/todos/${todoId}`);
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.statusCode).toEqual(res.status());
    });

    test("should return 422 with todoId error when invalid id passed", async () => {
      const res = await apiContext.get(`/api/v1/todos/__1`);
      const json = await res.json();
      expect(res.status()).toEqual(422);
      expect(json.statusCode).toEqual(res.status());
      expect(json.errors).toContainEqual(
        expect.objectContaining({ todoId: expect.anything() })
      );
    });
  });

  test.describe("DELETE:/api/v1/todos/:id - Delete Todo", () => {
    test("should delete todo", async () => {
      const res = await apiContext.delete(`/api/v1/todos/${todoId}`);
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.statusCode).toEqual(res.status());
    });
  });
});


================================================
FILE: e2e/routes/healthcheck.test.js
================================================
import { test, expect } from "@playwright/test";
import { getApiContext } from "../common.js";

let apiContext;

test.describe("Healthcheck", () => {
  test.beforeAll(async ({ playwright }) => {
    apiContext = await getApiContext(playwright);
  });
  test.afterAll(async ({}) => {
    await apiContext.dispose();
  });

  test("should return ok", async ({ page }) => {
    const res = await apiContext.get("/api/v1/healthcheck");
    expect(res.ok()).toBeTruthy();
  });
});


================================================
FILE: e2e/routes/seeds/chat-app.test.js
================================================
import { test, expect } from "@playwright/test";
import { getApiContext } from "../../common.js";
import { clearDB } from "../../db.js";

let apiContext;

test.describe("Seed Chat App", () => {
  test.beforeAll(async ({ playwright }) => {
    apiContext = await getApiContext(playwright);
    await clearDB();
  });
  test.afterAll(async ({}) => {
    await apiContext.dispose();
  });

  test.describe("POST:/api/v1/seed/chat-app - Seed Chat", async () => {
    test("should seed Chat App DB", async ({ page }) => {
      const res = await apiContext.post("/api/v1/seed/chat-app");
      expect(res.status()).toEqual(201);
    });
  });
});


================================================
FILE: e2e/routes/seeds/ecommerce.test.js
================================================
import { test, expect } from "@playwright/test";
import { getApiContext } from "../../common.js";
import { clearDB } from "../../db.js";
import {
  CATEGORIES_COUNT,
  PRODUCTS_COUNT,
} from "../../../src/seeds/_constants.js";

let apiContext;

test.describe("Seed Ecommerce App", () => {
  test.beforeAll(async ({ playwright }) => {
    apiContext = await getApiContext(playwright);
    await clearDB();
  });
  test.afterAll(async ({}) => {
    await apiContext.dispose();
  });

  test.describe("POST:/api/v1/seed/ecommerce - Seed Ecommerce", async () => {
    test("should return 0 products before seed", async ({ page }) => {
      const res = await apiContext.get(
        "/api/v1/ecommerce/products?page=1&limit=1"
      );
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.totalProducts).toEqual(0);
    });
    test("should return 0 categories before seed", async ({ page }) => {
      const res = await apiContext.get(
        "/api/v1/ecommerce/categories?page=1&limit=1"
      );
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.totalCategories).toEqual(0);
    });
    test("should seed ecommerce DB", async ({ page }) => {
      const res = await apiContext.post("/api/v1/seed/ecommerce");
      expect(res.status()).toEqual(201);
    });
    test(`should return ${PRODUCTS_COUNT} products after seed`, async ({
      page,
    }) => {
      const res = await apiContext.get(
        "/api/v1/ecommerce/products?page=1&limit=1"
      );
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.totalProducts).toEqual(PRODUCTS_COUNT);
    });
    test(`should return ${CATEGORIES_COUNT} categories after seed`, async ({
      page,
    }) => {
      const res = await apiContext.get(
        "/api/v1/ecommerce/categories?page=1&limit=1"
      );
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.totalCategories).toEqual(CATEGORIES_COUNT);
    });
  });
});


================================================
FILE: e2e/routes/seeds/generated-credentials.test.js
================================================
import fs from "fs";
import { test, expect } from "@playwright/test";
import { getApiContext } from "../../common.js";

let apiContext;

test.describe("Get credentials", () => {
  test.beforeAll(async ({ playwright }) => {
    apiContext = await getApiContext(playwright);
  });
  test.afterAll(async ({}) => {
    await apiContext.dispose();
  });

  test.describe("GET:/api/v1/seed/generated-credentials - Get credentials", async () => {
    test("should return public/temp/seed-credentials.json content", async ({
      page,
    }) => {
      const seedCredentialsText = fs.readFileSync(
        "./public/temp/seed-credentials.json",
        "utf8"
      );
      const seedCredentials = JSON.parse(seedCredentialsText);
      const res = await apiContext.get("/api/v1/seed/generated-credentials");
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data).toMatchObject(seedCredentials);
    });
  });
});


================================================
FILE: e2e/routes/seeds/social-media.test.js
================================================
import { test, expect } from "@playwright/test";
import { getApiContext } from "../../common.js";
import { clearDB } from "../../db.js";
import { SOCIAL_POSTS_COUNT } from "../../../src/seeds/_constants.js";

let apiContext;

test.describe("Seed social-media App", () => {
  test.beforeAll(async ({ playwright }) => {
    apiContext = await getApiContext(playwright);
    await clearDB();
  });
  test.afterAll(async ({}) => {
    await apiContext.dispose();
  });

  test.describe("POST:/api/v1/seed/social-media - Seed social-media", async () => {
    test("should return 0 posts before seed", async ({ page }) => {
      const res = await apiContext.get(
        "/api/v1/social-media/posts?page=1&limit=1"
      );
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.totalPosts).toEqual(0);
    });
    test("should seed social-media DB", async ({ page }) => {
      const res = await apiContext.post("/api/v1/seed/social-media");
      expect(res.status()).toEqual(201);
    });
    test(`should return ${SOCIAL_POSTS_COUNT} post after seed`, async ({
      page,
    }) => {
      const res = await apiContext.get(
        "/api/v1/social-media/posts?page=1&limit=1"
      );
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.totalPosts).toEqual(SOCIAL_POSTS_COUNT);
    });
  });
});


================================================
FILE: e2e/routes/seeds/todo.test.js
================================================
import { test, expect } from "@playwright/test";
import { getApiContext } from "../../common.js";
import { clearDB } from "../../db.js";
import { TODOS_COUNT } from "../../../src/seeds/_constants.js";

let apiContext;

test.describe("Seed Todo App", () => {
  test.beforeAll(async ({ playwright }) => {
    apiContext = await getApiContext(playwright);
    await clearDB();
  });
  test.afterAll(async ({}) => {
    await apiContext.dispose();
  });

  test.describe("POST:/api/v1/seed/todos - Seed Todos", async () => {
    test("should return 0 todos before seed", async ({ page }) => {
      const res = await apiContext.get("/api/v1/todos");
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.length).toEqual(0);
    });

    test("should seed todo DB", async ({ page }) => {
      const res = await apiContext.post("/api/v1/seed/todos");
      expect(res.status()).toEqual(201);
    });

    test(`should return ${TODOS_COUNT} todos after seed`, async ({ page }) => {
      const res = await apiContext.get("/api/v1/todos");
      const json = await res.json();
      expect(res.status()).toEqual(200);
      expect(json.data.length).toEqual(TODOS_COUNT);
    });
  });
});


================================================
FILE: e2e/test-server.js
================================================
import dotenv from "dotenv";
dotenv.config({
  path: "../.env",
});
import { httpServer } from "../src/app.js";
import connectDB from "./db.js";

const PORT = process.env.PORT || 8080;

/**
 * Starting from Node.js v14 top-level await is available and it is only available in ES modules.
 * This means you can not use it with common js modules or Node version < 14.
 */
const majorNodeVersion = +process.env.NODE_VERSION?.split(".")[0] || 0;

const startServer = () => {
  httpServer.listen(PORT, () => {
    console.info(`📑 Visit the documentation at: http://localhost:${PORT}`);
    console.log("⚙️  Server is running on port: " + PORT);
  });
};

if (majorNodeVersion >= 14) {
  try {
    await connectDB();
    startServer();
  } catch (err) {
    console.log("Mongo db connect error: ", err);
  }
} else {
  connectDB()
    .then(() => {
      startServer();
    })
    .catch((err) => {
      console.log("Mongo db connect error: ", err);
    });
}


================================================
FILE: examples/apps/auth/.gitkeep
================================================


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/.eslintrc.cjs
================================================
module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react-hooks/recommended",
  ],
  ignorePatterns: ["dist", ".eslintrc.cjs"],
  parser: "@typescript-eslint/parser",
  plugins: ["react-refresh"],
  rules: {
    "react-refresh/only-export-components": [
      "warn",
      { allowConstantExport: true },
    ],
    "@typescript-eslint/no-explicit-any": ["off"],
  },
};


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/README.md
================================================
# Installation and setup

Create a `.env` file in the ROOT folder and copy past the content of the `.env.sample` file in it.

Run the following commands to start the server

```bash
npm install
npm run dev

# Make sure to keep the freeapi server running
```


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/index.html
================================================
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FreeAPI | Chat app example</title>
  </head>
  <body class="bg-dark text-white">
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/package.json
================================================
{
  "name": "vite-chat-app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@headlessui/react": "^1.7.16",
    "@heroicons/react": "^2.0.18",
    "axios": "^1.7.4",
    "moment": "^2.29.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.14.2",
    "socket.io-client": "^4.7.2"
  },
  "devDependencies": {
    "@types/react": "^18.2.15",
    "@types/react-dom": "^18.2.7",
    "@typescript-eslint/eslint-plugin": "^6.0.0",
    "@typescript-eslint/parser": "^6.0.0",
    "@vitejs/plugin-react": "^4.0.3",
    "autoprefixer": "^10.4.14",
    "eslint": "^8.45.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.3",
    "postcss": "^8.4.27",
    "tailwindcss": "^3.3.3",
    "typescript": "^5.0.2",
    "vite": "^4.5.4"
  },
  "resolutions": {
    "cross-spawn": "^7.0.5",
    "nanoid": "^3.3.8"
  }
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/postcss.config.js
================================================
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/App.tsx
================================================
// Importing required modules and components from the react-router-dom and other files.
import { Routes, Route, Navigate } from "react-router-dom";
import Login from "./pages/login";
import Register from "./pages/register";
import ChatPage from "./pages/chat";
import { useAuth } from "./context/AuthContext";
import PrivateRoute from "./components/PrivateRoute";
import PublicRoute from "./components/PublicRoute";

// Main App component
const App = () => {
  // Extracting 'token' and 'user' from the authentication context
  const { token, user } = useAuth();

  return (
    <Routes>
      {/* Root route: Redirects to chat if the user is logged in, else to the login page */}
      <Route
        path="/"
        element={
          token && user?._id ? (
            <Navigate to="/chat" />
          ) : (
            <Navigate to="/login" />
          )
        }
      ></Route>

      {/* Private chat route: Can only be accessed by authenticated users */}
      <Route
        path="/chat"
        element={
          <PrivateRoute>
            <ChatPage />
          </PrivateRoute>
        }
      />

      {/* Public login route: Accessible by everyone */}
      <Route
        path="/login"
        element={
          <PublicRoute>
            <Login />
          </PublicRoute>
        }
      />

      {/* Public register route: Accessible by everyone */}
      <Route
        path="/register"
        element={
          <PublicRoute>
            <Register />
          </PublicRoute>
        }
      />

      {/* Wildcard route for undefined paths. Shows a 404 error */}
      <Route path="*" element={<p>404 Not found</p>} />
    </Routes>
  );
};

// Exporting the App component to be used in other parts of the application
export default App;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/api/index.ts
================================================
// Import necessary modules and utilities
import axios from "axios";
import { LocalStorage } from "../utils";

// Create an Axios instance for API requests
const apiClient = axios.create({
  baseURL: import.meta.env.VITE_SERVER_URI,
  withCredentials: true,
  timeout: 120000,
});

// Add an interceptor to set authorization header with user token before requests
apiClient.interceptors.request.use(
  function (config) {
    // Retrieve user token from local storage
    const token = LocalStorage.get("token");
    // Set authorization header with bearer token
    config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);

// API functions for different actions
const loginUser = (data: { username: string; password: string }) => {
  return apiClient.post("/users/login", data);
};

const registerUser = (data: {
  email: string;
  password: string;
  username: string;
}) => {
  return apiClient.post("/users/register", data);
};

const logoutUser = () => {
  return apiClient.post("/users/logout");
};

const getAvailableUsers = () => {
  return apiClient.get("/chat-app/chats/users");
};

const getUserChats = () => {
  return apiClient.get(`/chat-app/chats`);
};

const createUserChat = (receiverId: string) => {
  return apiClient.post(`/chat-app/chats/c/${receiverId}`);
};

const createGroupChat = (data: { name: string; participants: string[] }) => {
  return apiClient.post(`/chat-app/chats/group`, data);
};

const getGroupInfo = (chatId: string) => {
  return apiClient.get(`/chat-app/chats/group/${chatId}`);
};

const updateGroupName = (chatId: string, name: string) => {
  return apiClient.patch(`/chat-app/chats/group/${chatId}`, { name });
};

const deleteGroup = (chatId: string) => {
  return apiClient.delete(`/chat-app/chats/group/${chatId}`);
};

const deleteOneOnOneChat = (chatId: string) => {
  return apiClient.delete(`/chat-app/chats/remove/${chatId}`);
};

const addParticipantToGroup = (chatId: string, participantId: string) => {
  return apiClient.post(`/chat-app/chats/group/${chatId}/${participantId}`);
};

const removeParticipantFromGroup = (chatId: string, participantId: string) => {
  return apiClient.delete(`/chat-app/chats/group/${chatId}/${participantId}`);
};

const getChatMessages = (chatId: string) => {
  return apiClient.get(`/chat-app/messages/${chatId}`);
};

const sendMessage = (chatId: string, content: string, attachments: File[]) => {
  const formData = new FormData();
  if (content) {
    formData.append("content", content);
  }
  attachments?.map((file) => {
    formData.append("attachments", file);
  });
  return apiClient.post(`/chat-app/messages/${chatId}`, formData);
};

const deleteMessage = (chatId: string, messageId: string) => {
  return apiClient.delete(`/chat-app/messages/${chatId}/${messageId}`);
};

// Export all the API functions
export {
  addParticipantToGroup,
  createGroupChat,
  createUserChat,
  deleteGroup,
  deleteOneOnOneChat,
  getAvailableUsers,
  getChatMessages,
  getGroupInfo,
  getUserChats,
  loginUser,
  logoutUser,
  registerUser,
  removeParticipantFromGroup,
  sendMessage,
  updateGroupName,
  deleteMessage,
};


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/Button.tsx
================================================
import React from "react";
import { classNames } from "../utils";

const Button: React.FC<
  React.ButtonHTMLAttributes<HTMLButtonElement> & {
    fullWidth?: boolean;
    severity?: "primary" | "secondary" | "danger";
    size?: "base" | "small";
  }
> = ({ fullWidth, severity = "primary", size = "base", ...props }) => {
  return (
    <>
      <button
        {...props}
        className={classNames(
          "rounded-full inline-flex flex-shrink-0 justify-center items-center text-center text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white shadow-sm",
          fullWidth ? "w-full" : "",
          severity === "secondary"
            ? "bg-secondary hover:bg-secondary/80 disabled:bg-secondary/50 outline outline-[1px] outline-zinc-400"
            : severity === "danger"
            ? "bg-danger hover:bg-danger/80 disabled:bg-danger/50"
            : "bg-primary hover:bg-primary/80 disabled:bg-primary/50",
          size === "small" ? "text-sm px-3 py-1.5" : "text-base px-4 py-3",
          props.className || ""
        )}
      >
        {props.children}
      </button>
    </>
  );
};

export default Button;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/Input.tsx
================================================
import React from "react";
import { classNames } from "../utils";

const Input: React.FC<React.InputHTMLAttributes<HTMLInputElement>> = (
  props
) => {
  return (
    <input
      {...props}
      className={classNames(
        "block w-full rounded-xl outline outline-[1px] outline-zinc-400 border-0 py-4 px-5 bg-secondary text-white font-light placeholder:text-white/70",
        props.className || ""
      )}
    />
  );
};

export default Input;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/Loader.tsx
================================================
const Loader = () => {
  return (
    <div className="flex space-x-2 w-full h-screen fixed inset-0 bg-zinc-700/50 z-50 justify-center items-center">
      <div aria-label="Loading..." role="status">
        <svg className="h-12 w-12 animate-spin" viewBox="3 3 18 18">
          <path
            className="fill-white"
            d="M12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19C15.866 19 19 15.866 19 12C19 8.13401 15.866 5 12 5ZM3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12Z"
          ></path>
          <path
            className="fill-secondary"
            d="M16.9497 7.05015C14.2161 4.31648 9.78392 4.31648 7.05025 7.05015C6.65973 7.44067 6.02656 7.44067 5.63604 7.05015C5.24551 6.65962 5.24551 6.02646 5.63604 5.63593C9.15076 2.12121 14.8492 2.12121 18.364 5.63593C18.7545 6.02646 18.7545 6.65962 18.364 7.05015C17.9734 7.44067 17.3403 7.44067 16.9497 7.05015Z"
          ></path>
        </svg>
      </div>
    </div>
  );
};

export default Loader;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/PrivateRoute.tsx
================================================
// Import required modules and types from React and react-router-dom libraries
import React, { ReactNode } from "react";
import { Navigate } from "react-router-dom";

// Import authentication context for retrieving user and token information
import { useAuth } from "../context/AuthContext";

// Define a PrivateRoute component that wraps child components to ensure user authentication
const PrivateRoute: React.FC<{ children: ReactNode }> = ({ children }) => {
  // Destructure token and user details from the authentication context
  const { token, user } = useAuth();

  // If there's no token or user ID, redirect to the login page
  if (!token || !user?._id) return <Navigate to="/login" replace />;

  // If authenticated, render the child components
  return children;
};

// Export the PrivateRoute component for use in other parts of the application
export default PrivateRoute;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/PublicRoute.tsx
================================================
// Import necessary libraries and types
import React, { ReactNode } from "react";
import { Navigate } from "react-router-dom";
import { useAuth } from "../context/AuthContext";

// Define the PublicRoute component which takes in children as its prop
const PublicRoute: React.FC<{ children: ReactNode }> = ({ children }) => {
  // Destructure token and user from the authentication context
  const { token, user } = useAuth();

  // If there is a valid token and user ID, navigate the user to the chat page
  if (token && user?._id) return <Navigate to="/chat" replace />;

  // If no token or user ID exists, render the child components as they are
  return children;
};

// Export the PublicRoute component for use in other parts of the application
export default PublicRoute;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/Select.tsx
================================================
import { Combobox } from "@headlessui/react";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/20/solid";
import React, { useEffect, useState } from "react";
import { classNames } from "../utils";

const Select: React.FC<{
  options: {
    value: string;
    label: string;
  }[];
  value: string;
  onChange: (value: { value: string; label: string }) => void;
  placeholder: string;
}> = ({ options, value, placeholder, onChange }) => {
  const [localOptions, setLocalOptions] = useState<typeof options>([]);

  useEffect(() => {
    setLocalOptions(options);
  }, [options]);

  return (
    <Combobox
      className={"w-full"}
      as="div"
      value={options.find((o) => o.value === value)}
      onChange={(val: any) => onChange(val)}
    >
      <div className="relative mt-2">
        <Combobox.Button className="w-full">
          <Combobox.Input
            placeholder={placeholder}
            className="block w-full rounded-xl border-0 py-4 px-5 bg-secondary outline outline-[1px] outline-zinc-400 text-white font-light placeholder:text-white/70 focus:ring-[1px] focus:ring-white"
            onChange={(e) => {
              setLocalOptions(
                options.filter((op) => op.label.includes(e.target.value))
              );
            }}
            displayValue={(option: (typeof options)[0]) => option?.label}
          />
        </Combobox.Button>
        <Combobox.Button className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none">
          <ChevronUpDownIcon
            className="h-5 w-5 text-zinc-400"
            aria-hidden="true"
          />
        </Combobox.Button>

        {localOptions.length > 0 && (
          <Combobox.Options className="outline outline-[1px] outline-zinc-400 absolute z-10 mt-2 p-2 max-h-60 w-full overflow-auto rounded-2xl bg-secondary text-base shadow-lg ring-opacity-5 focus:outline-none sm:text-sm">
            {localOptions.map((option) => (
              <Combobox.Option
                key={option.value}
                value={option}
                className={({ active }) =>
                  classNames(
                    "cursor-pointer relative rounded-2xl select-none py-4 pl-3 pr-9",
                    active ? "bg-dark text-white" : "text-white"
                  )
                }
              >
                {({ active, selected }) => (
                  <>
                    <span
                      className={classNames(
                        "block truncate",
                        selected ? "font-semibold" : ""
                      )}
                    >
                      {option.label}
                    </span>

                    {selected && (
                      <span
                        className={classNames(
                          "absolute inset-y-0 right-0 flex items-center pr-4",
                          active ? "text-white" : "text-indigo-600"
                        )}
                      >
                        <CheckIcon className="h-5 w-5" aria-hidden="true" />
                      </span>
                    )}
                  </>
                )}
              </Combobox.Option>
            ))}
          </Combobox.Options>
        )}
      </div>
    </Combobox>
  );
};

export default Select;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/AddChatModal.tsx
================================================
import { Dialog, Switch, Transition } from "@headlessui/react";
import {
  UserGroupIcon,
  XCircleIcon,
  XMarkIcon,
} from "@heroicons/react/20/solid";
import { Fragment, useEffect, useState } from "react";
import { createGroupChat, createUserChat, getAvailableUsers } from "../../api";
import { ChatListItemInterface } from "../../interfaces/chat";
import { UserInterface } from "../../interfaces/user";
import { classNames, requestHandler } from "../../utils";
import Button from "../Button";
import Input from "../Input";
import Select from "../Select";

const AddChatModal: React.FC<{
  open: boolean;
  onClose: () => void;
  onSuccess: (chat: ChatListItemInterface) => void;
}> = ({ open, onClose, onSuccess }) => {
  // State to store the list of users, initialized as an empty array
  const [users, setUsers] = useState<UserInterface[]>([]);
  // State to store the name of a group, initialized as an empty string
  const [groupName, setGroupName] = useState("");
  // State to determine if the chat is a group chat, initialized as false
  const [isGroupChat, setIsGroupChat] = useState(false);
  // State to store the list of participants in a group chat, initialized as an empty array
  const [groupParticipants, setGroupParticipants] = useState<string[]>([]);
  // State to store the ID of a selected user, initialized as null
  const [selectedUserId, setSelectedUserId] = useState<null | string>(null);
  // State to determine if a chat is currently being created, initialized as false
  const [creatingChat, setCreatingChat] = useState(false);

  // Function to fetch users
  const getUsers = async () => {
    // Handle the request to get available users
    requestHandler(
      // Callback to fetch available users
      async () => await getAvailableUsers(),
      null, // No loading setter callback provided
      // Success callback
      (res) => {
        const { data } = res; // Extract data from response
        setUsers(data || []); // Set users data or an empty array if data is absent
      },
      alert // Use the alert as the error handler
    );
  };

  // Function to create a new chat with a user
  const createNewChat = async () => {
    // If no user is selected, show an alert
    if (!selectedUserId) return alert("Please select a user");

    // Handle the request to create a chat
    await requestHandler(
      // Callback to create a user chat
      async () => await createUserChat(selectedUserId),
      setCreatingChat, // Callback to handle loading state
      // Success callback
      (res) => {
        const { data } = res; // Extract data from response
        // If chat already exists with the selected user
        if (res.statusCode === 200) {
          alert("Chat with selected user already exists");
          return;
        }
        onSuccess(data); // Execute the onSuccess function with received data
        handleClose(); // Close the modal or popup
      },
      alert // Use the alert as the error handler
    );
  };

  // Function to create a new group chat
  const createNewGroupChat = async () => {
    // Check if a group name is provided
    if (!groupName) return alert("Group name is required");
    // Ensure there are at least 2 group participants
    if (!groupParticipants.length || groupParticipants.length < 2)
      return alert("There must be at least 2 group participants");

    // Handle the request to create a group chat
    await requestHandler(
      // Callback to create a group chat with name and participants
      async () =>
        await createGroupChat({
          name: groupName,
          participants: groupParticipants,
        }),
      setCreatingChat, // Callback to handle loading state
      // Success callback
      (res) => {
        const { data } = res; // Extract data from response
        onSuccess(data); // Execute the onSuccess function with received data
        handleClose(); // Close the modal or popup
      },
      alert // Use the alert as the error handler
    );
  };

  // Function to reset local state values and close the modal/dialog
  const handleClose = () => {
    // Clear the list of users
    setUsers([]);
    // Reset the selected user ID
    setSelectedUserId("");
    // Clear the group name
    setGroupName("");
    // Clear the group participants list
    setGroupParticipants([]);
    // Set the chat type to not be a group chat
    setIsGroupChat(false);
    // Execute the onClose callback/function
    onClose();
  };

  // useEffect hook to perform side effects based on changes in the component lifecycle or state/props
  useEffect(() => {
    // Check if the modal/dialog is not open
    if (!open) return;
    // Fetch users if the modal/dialog is open
    getUsers();
    // The effect depends on the 'open' value. Whenever 'open' changes, the effect will re-run.
  }, [open]);

  return (
    <Transition.Root show={open} as={Fragment}>
      <Dialog as="div" className="relative z-10" onClose={handleClose}>
        <Transition.Child
          as={Fragment}
          enter="ease-out duration-300"
          enterFrom="opacity-0"
          enterTo="opacity-100"
          leave="ease-in duration-200"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <div className="fixed inset-0 bg-black/50 bg-opacity-75 transition-opacity" />
        </Transition.Child>

        <div className="fixed inset-0 z-10 overflow-y-visible">
          <div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
            <Transition.Child
              as={Fragment}
              enter="ease-out duration-300"
              enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
              enterTo="opacity-100 translate-y-0 sm:scale-100"
              leave="ease-in duration-200"
              leaveFrom="opacity-100 translate-y-0 sm:scale-100"
              leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
            >
              <Dialog.Panel
                className="relative transform overflow-x-hidden rounded-lg bg-dark px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-3xl sm:p-6"
                style={{
                  overflow: "inherit",
                }}
              >
                <div>
                  <div className="flex justify-between items-center">
                    <Dialog.Title
                      as="h3"
                      className="text-lg font-semibold leading-6 text-white"
                    >
                      Create chat
                    </Dialog.Title>
                    <button
                      type="button"
                      className="rounded-md bg-transparent text-zinc-400 hover:text-zinc-600 focus:outline-none focus:ring-1 focus:ring-white focus:ring-offset-2"
                      onClick={() => handleClose()}
                    >
                      <span className="sr-only">Close</span>
                      <XMarkIcon className="h-6 w-6" aria-hidden="true" />
                    </button>
                  </div>
                </div>
                <div>
                  <Switch.Group as="div" className="flex items-center my-5">
                    <Switch
                      checked={isGroupChat}
                      onChange={setIsGroupChat}
                      className={classNames(
                        isGroupChat ? "bg-secondary" : "bg-zinc-200",
                        "relative outline outline-[1px] outline-white inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:ring-0"
                      )}
                    >
                      <span
                        aria-hidden="true"
                        className={classNames(
                          isGroupChat
                            ? "translate-x-5 bg-success"
                            : "translate-x-0 bg-white",
                          "pointer-events-none inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out"
                        )}
                      />
                    </Switch>
                    <Switch.Label as="span" className="ml-3 text-sm">
                      <span
                        className={classNames(
                          "font-medium text-white",
                          isGroupChat ? "" : "opacity-40"
                        )}
                      >
                        Is it a group chat?
                      </span>{" "}
                    </Switch.Label>
                  </Switch.Group>
                  {isGroupChat ? (
                    <div className="my-5">
                      <Input
                        placeholder={"Enter a group name..."}
                        value={groupName}
                        onChange={(e) => {
                          setGroupName(e.target.value);
                        }}
                      />
                    </div>
                  ) : null}
                  <div className="my-5">
                    <Select
                      placeholder={
                        isGroupChat
                          ? "Select group participants..."
                          : "Select a user to chat..."
                      }
                      value={isGroupChat ? "" : selectedUserId || ""}
                      options={users.map((user) => {
                        return {
                          label: user.username,
                          value: user._id,
                        };
                      })}
                      onChange={({ value }) => {
                        if (isGroupChat && !groupParticipants.includes(value)) {
                          // if user is creating a group chat track the participants in an array
                          setGroupParticipants([...groupParticipants, value]);
                        } else {
                          setSelectedUserId(value);
                          // if user is creating normal chat just get a single user
                        }
                      }}
                    />
                  </div>
                  {isGroupChat ? (
                    <div className="my-5">
                      <span
                        className={classNames(
                          "font-medium text-white inline-flex items-center"
                        )}
                      >
                        <UserGroupIcon className="h-5 w-5 mr-2" /> Selected
                        participants
                      </span>{" "}
                      <div className="flex justify-start items-center flex-wrap gap-2 mt-3">
                        {users
                          .filter((user) =>
                            groupParticipants.includes(user._id)
                          )
                          ?.map((participant) => {
                            return (
                              <div
                                className="inline-flex bg-secondary rounded-full p-2 border-[1px] border-zinc-400 items-center gap-2"
                                key={participant._id}
                              >
                                <img
                                  className="h-6 w-6 rounded-full object-cover"
                                  src={participant.avatar.url}
                                />
                                <p className="text-white">
                                  {participant.username}
                                </p>
                                <XCircleIcon
                                  role="button"
                                  className="w-6 h-6 hover:text-primary cursor-pointer"
                                  onClick={() => {
                                    setGroupParticipants(
                                      groupParticipants.filter(
                                        (p) => p !== participant._id
                                      )
                                    );
                                  }}
                                />
                              </div>
                            );
                          })}
                      </div>
                    </div>
                  ) : null}
                </div>
                <div className="mt-5 flex justify-between items-center gap-4">
                  <Button
                    disabled={creatingChat}
                    severity={"secondary"}
                    onClick={handleClose}
                    className="w-1/2"
                  >
                    Close
                  </Button>
                  <Button
                    disabled={creatingChat}
                    onClick={isGroupChat ? createNewGroupChat : createNewChat}
                    className="w-1/2"
                  >
                    Create
                  </Button>
                </div>
              </Dialog.Panel>
            </Transition.Child>
          </div>
        </div>
      </Dialog>
    </Transition.Root>
  );
};

export default AddChatModal;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/ChatItem.tsx
================================================
import {
  EllipsisVerticalIcon,
  PaperClipIcon,
  TrashIcon,
} from "@heroicons/react/20/solid";
import { InformationCircleIcon } from "@heroicons/react/24/outline";
import moment from "moment";
import React, { useState } from "react";
import { deleteOneOnOneChat } from "../../api";
import { useAuth } from "../../context/AuthContext";
import { ChatListItemInterface } from "../../interfaces/chat";
import { classNames, getChatObjectMetadata, requestHandler } from "../../utils";
import GroupChatDetailsModal from "./GroupChatDetailsModal";

const ChatItem: React.FC<{
  chat: ChatListItemInterface;
  onClick: (chat: ChatListItemInterface) => void;
  isActive?: boolean;
  unreadCount?: number;
  onChatDelete: (chatId: string) => void;
}> = ({ chat, onClick, isActive, unreadCount = 0, onChatDelete }) => {
  const { user } = useAuth();
  const [openOptions, setOpenOptions] = useState(false);
  const [openGroupInfo, setOpenGroupInfo] = useState(false);

  // Define an asynchronous function named 'deleteChat'.
  const deleteChat = async () => {
    await requestHandler(
      //  A callback function that performs the deletion of a one-on-one chat by its ID.
      async () => await deleteOneOnOneChat(chat._id),
      null,
      // A callback function to be executed on success. It will call 'onChatDelete'
      // function with the chat's ID as its parameter.
      () => {
        onChatDelete(chat._id);
      },
      // The 'alert' function (likely to display error messages to the user.
      alert
    );
  };

  if (!chat) return;
  return (
    <>
      <GroupChatDetailsModal
        open={openGroupInfo}
        onClose={() => {
          setOpenGroupInfo(false);
        }}
        chatId={chat._id}
        onGroupDelete={onChatDelete}
      />
      <div
        role="button"
        onClick={() => onClick(chat)}
        onMouseLeave={() => setOpenOptions(false)}
        className={classNames(
          "group p-4 my-2 flex justify-between gap-3 items-start cursor-pointer rounded-3xl hover:bg-secondary",
          isActive ? "border-[1px] border-zinc-500 bg-secondary" : "",
          unreadCount > 0
            ? "border-[1px] border-success bg-success/20 font-bold"
            : ""
        )}
      >
        <button
          onClick={(e) => {
            e.stopPropagation();
            setOpenOptions(!openOptions);
          }}
          className="self-center p-1 relative"
        >
          <EllipsisVerticalIcon className="h-6 group-hover:w-6 group-hover:opacity-100 w-0 opacity-0 transition-all ease-in-out duration-100 text-zinc-300" />
          <div
            className={classNames(
              "z-20 text-left absolute bottom-0 translate-y-full text-sm w-52 bg-dark rounded-2xl p-2 shadow-md border-[1px] border-secondary",
              openOptions ? "block" : "hidden"
            )}
          >
            {chat.isGroupChat ? (
              <p
                onClick={(e) => {
                  e.stopPropagation();
                  setOpenGroupInfo(true);
                }}
                role="button"
                className="p-4 w-full rounded-lg inline-flex items-center hover:bg-secondary"
              >
                <InformationCircleIcon className="h-4 w-4 mr-2" /> About group
              </p>
            ) : (
              <p
                onClick={(e) => {
                  e.stopPropagation();
                  const ok = confirm(
                    "Are you sure you want to delete this chat?"
                  );
                  if (ok) {
                    deleteChat();
                  }
                }}
                role="button"
                className="p-4 text-danger rounded-lg w-full inline-flex items-center hover:bg-secondary"
              >
                <TrashIcon className="h-4 w-4 mr-2" />
                Delete chat
              </p>
            )}
          </div>
        </button>
        <div className="flex justify-center items-center flex-shrink-0">
          {chat.isGroupChat ? (
            <div className="w-12 relative h-12 flex-shrink-0 flex justify-start items-center flex-nowrap">
              {chat.participants.slice(0, 3).map((participant, i) => {
                return (
                  <img
                    key={participant._id}
                    src={participant.avatar.url}
                    className={classNames(
                      "w-8 h-8 border-[1px] border-white rounded-full absolute outline outline-4 outline-dark group-hover:outline-secondary",
                      i === 0
                        ? "left-0 z-[3]"
                        : i === 1
                        ? "left-2.5 z-[2]"
                        : i === 2
                        ? "left-[18px] z-[1]"
                        : ""
                    )}
                  />
                );
              })}
            </div>
          ) : (
            <img
              src={getChatObjectMetadata(chat, user!).avatar}
              className="w-12 h-12 rounded-full"
            />
          )}
        </div>
        <div className="w-full">
          <p className="truncate-1">
            {getChatObjectMetadata(chat, user!).title}
          </p>
          <div className="w-full inline-flex items-center text-left">
            {chat.lastMessage && chat.lastMessage.attachments.length > 0 ? (
              // If last message is an attachment show paperclip
              <PaperClipIcon className="text-white/50 h-3 w-3 mr-2 flex flex-shrink-0" />
            ) : null}
            <small className="text-white/50 truncate-1 text-sm text-ellipsis inline-flex items-center">
              {getChatObjectMetadata(chat, user!).lastMessage}
            </small>
          </div>
        </div>
        <div className="flex text-white/50 h-full text-sm flex-col justify-between items-end">
          <small className="mb-2 inline-flex flex-shrink-0 w-max">
            {moment(chat.updatedAt).add("TIME_ZONE", "hours").fromNow(true)}
          </small>

          {/* Unread count will be > 0 when user is on another chat and there is new message in a chat which is not currently active on user's screen */}
          {unreadCount <= 0 ? null : (
            <span className="bg-success h-2 w-2 aspect-square flex-shrink-0 p-2 text-white text-xs rounded-full inline-flex justify-center items-center">
              {unreadCount > 9 ? "9+" : unreadCount}
            </span>
          )}
        </div>
      </div>
    </>
  );
};

export default ChatItem;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/GroupChatDetailsModal.tsx
================================================
import { Dialog, Transition } from "@headlessui/react";
import {
  PencilIcon,
  TrashIcon,
  UserGroupIcon,
  UserPlusIcon,
  XMarkIcon,
} from "@heroicons/react/20/solid";
import React, { Fragment, useEffect, useState } from "react";
import {
  addParticipantToGroup,
  deleteGroup,
  getAvailableUsers,
  getGroupInfo,
  removeParticipantFromGroup,
  updateGroupName,
} from "../../api";
import { useAuth } from "../../context/AuthContext";
import { ChatListItemInterface } from "../../interfaces/chat";
import { UserInterface } from "../../interfaces/user";
import { requestHandler } from "../../utils";
import Button from "../Button";
import Input from "../Input";
import Select from "../Select";

const GroupChatDetailsModal: React.FC<{
  open: boolean;
  onClose: () => void;
  chatId: string;
  onGroupDelete: (chatId: string) => void;
}> = ({ open, onClose, chatId, onGroupDelete }) => {
  const { user } = useAuth();
  // State to manage the UI flag for adding a participant
  const [addingParticipant, setAddingParticipant] = useState(false);
  // State to manage the UI flag for renaming a group
  const [renamingGroup, setRenamingGroup] = useState(false);

  // State to capture the ID of the participant to be added
  const [participantToBeAdded, setParticipantToBeAdded] = useState("");
  // State to capture the new name when renaming a group
  const [newGroupName, setNewGroupName] = useState("");

  // State to store the current group details, initially set to null
  const [groupDetails, setGroupDetails] =
    useState<ChatListItemInterface | null>(null);

  // State to manage a list of users, initially set as an empty array
  const [users, setUsers] = useState<UserInterface[]>([]);

  // Function to handle the update of the group name.
  const handleGroupNameUpdate = async () => {
    // Check if the new group name is provided.
    if (!newGroupName) return alert("Group name is required");

    // Request to update the group name.
    requestHandler(
      // Call to update the group name with the provided chatId and newGroupName.
      async () => await updateGroupName(chatId, newGroupName),
      null,
      // On successful update, set the new group details and other related states.
      (res) => {
        const { data } = res;
        setGroupDetails(data); // Set the new group details.
        setNewGroupName(data.name); // Set the new group name state.
        setRenamingGroup(false); // Set the state to not renaming.
        alert("Group name updated to " + data.name); // Alert the user about the update.
      },
      alert // Use default alert for any error messages.
    );
  };

  // Function to retrieve available users.
  const getUsers = async () => {
    requestHandler(
      // Call to get the list of available users.
      async () => await getAvailableUsers(),
      null,
      // On successful retrieval, set the users' state.
      (res) => {
        const { data } = res;
        setUsers(data || []);
      },
      alert // Use default alert for any error messages.
    );
  };

  // Function to delete a group chat.
  const deleteGroupChat = async () => {
    // Check if the user is the admin of the group before deletion.
    if (groupDetails?.admin !== user?._id) {
      return alert("You are not the admin of the group");
    }

    // Request to delete the group chat.
    requestHandler(
      // Call to delete the group using the provided chatId.
      async () => await deleteGroup(chatId),
      null,
      // On successful deletion, trigger onGroupDelete and close any modals/dialogs.
      () => {
        onGroupDelete(chatId);
        handleClose();
      },
      alert // Use default alert for any error messages.
    );
  };

  const removeParticipant = async (participantId: string) => {
    requestHandler(
      // This is the main request function to remove a participant from the group.
      async () => await removeParticipantFromGroup(chatId, participantId),
      // Null represents an optional loading state callback
      null,
      // This is the callback after the request is successful.
      () => {
        // Copy the existing group details.
        const updatedGroupDetails = {
          ...groupDetails,
          // Update the participants list by filtering out the removed participant.
          participants:
            (groupDetails?.participants &&
              groupDetails?.participants?.filter(
                (p) => p._id !== participantId
              )) ||
            [],
        };
        // Update the state with the modified group details.
        setGroupDetails(updatedGroupDetails as ChatListItemInterface);
        // Inform the user that the participant has been removed.
        alert("Participant removed");
      },
      // This may be a generic error alert or error handling function if the request fails.
      alert
    );
  };

  // Function to add a participant to a chat group.
  const addParticipant = async () => {
    // Check if there's a participant selected to be added.
    if (!participantToBeAdded)
      return alert("Please select a participant to add.");
    // Make a request to add the participant to the group.
    requestHandler(
      // Actual request to add the participant.
      async () => await addParticipantToGroup(chatId, participantToBeAdded),
      // No loading callback provided, so passing `null`.
      null,
      // Callback on success.
      (res) => {
        // Destructure the response to get the data.
        const { data } = res;
        // Create an updated group details object.
        const updatedGroupDetails = {
          ...groupDetails,
          participants: data?.participants || [],
        };
        // Update the group details state with the new details.
        setGroupDetails(updatedGroupDetails as ChatListItemInterface);
        // Alert the user that the participant was added.
        alert("Participant added");
      },
      // Use the `alert` function as the fallback error handler.
      alert
    );
  };

  // Function to fetch group information
  const fetchGroupInformation = async () => {
    requestHandler(
      // Fetching group info for a specific chatId
      async () => await getGroupInfo(chatId),
      // Placeholder for a loading callback (currently set to null)
      null,
      // If the request is successful, destructure the response and set group details and the group name
      (res) => {
        const { data } = res;
        setGroupDetails(data);
        setNewGroupName(data?.name || "");
      },
      // If the request fails, show an alert
      alert
    );
  };

  // Function to handle modal or component closure
  const handleClose = () => {
    onClose();
  };

  // React's effect hook to perform side effects, here to fetch group information and users
  useEffect(() => {
    // If the modal or component isn't open, exit early
    if (!open) return;

    // Fetch group information and users when the modal or component opens
    fetchGroupInformation();
    getUsers();
  }, [open]); // The effect is dependent on the 'open' state or prop, so it re-runs whenever 'open' changes

  return (
    <Transition.Root show={open} as={Fragment}>
      <Dialog as="div" className="relative z-40" onClose={handleClose}>
        <Transition.Child
          as={Fragment}
          enter="transform transition ease-in-out duration-500 sm:duration-700"
          enterFrom="opacity-0"
          enterTo="opacity-100"
          leave="transform transition ease-in-out duration-500 sm:duration-700"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <div className="fixed inset-0 bg-black/50" />
        </Transition.Child>
        <div className="fixed inset-0 overflow-hidden">
          <div className="absolute inset-0 overflow-hidden">
            <div className="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 sm:pl-16">
              <Transition.Child
                as={Fragment}
                enter="transform transition ease-in-out duration-500 sm:duration-700"
                enterFrom="translate-x-full"
                enterTo="translate-x-0"
                leave="transform transition ease-in-out duration-500 sm:duration-700"
                leaveFrom="translate-x-0"
                leaveTo="translate-x-full"
              >
                <Dialog.Panel className="pointer-events-auto w-screen max-w-2xl">
                  <div className="flex h-full flex-col overflow-y-scroll bg-secondary py-6 shadow-xl">
                    <div className="px-4 sm:px-6">
                      <div className="flex items-start justify-between">
                        <div className="ml-3 flex h-7 items-center">
                          <button
                            type="button"
                            className="relative rounded-md bg-secondary text-zinc-400 hover:text-zinc-500 focus:outline-none"
                            onClick={handleClose}
                          >
                            <span className="absolute -inset-2.5" />
                            <span className="sr-only">Close panel</span>
                            <XMarkIcon className="h-6 w-6" aria-hidden="true" />
                          </button>
                        </div>
                      </div>
                    </div>
                    <div className="relative mt-6 flex-1 px-4 sm:px-6">
                      <div className="flex flex-col justify-center items-start">
                        <div className="flex pl-16 justify-center items-center relative w-full h-max gap-3">
                          {groupDetails?.participants.slice(0, 3).map((p) => {
                            return (
                              <img
                                className="w-24 h-24 -ml-16 rounded-full outline outline-4 outline-secondary"
                                key={p._id}
                                src={p.avatar.url}
                                alt="avatar"
                              />
                            );
                          })}
                          {groupDetails?.participants &&
                          groupDetails?.participants.length > 3 ? (
                            <p>+{groupDetails?.participants.length - 3}</p>
                          ) : null}
                        </div>
                        <div className="w-full flex flex-col justify-center items-center text-center">
                          {renamingGroup ? (
                            <div className="w-full flex justify-center items-center mt-5 gap-2">
                              <Input
                                placeholder="Enter new group name..."
                                value={newGroupName}
                                onChange={(e) =>
                                  setNewGroupName(e.target.value)
                                }
                              />
                              <Button
                                severity="primary"
                                onClick={handleGroupNameUpdate}
                              >
                                Save
                              </Button>
                              <Button
                                severity="secondary"
                                onClick={() => setRenamingGroup(false)}
                              >
                                Cancel
                              </Button>
                            </div>
                          ) : (
                            <div className="w-full inline-flex justify-center items-center text-center mt-5">
                              <h1 className="text-2xl font-semibold truncate-1">
                                {groupDetails?.name}
                              </h1>
                              {groupDetails?.admin === user?._id ? (
                                <button onClick={() => setRenamingGroup(true)}>
                                  <PencilIcon className="w-5 h-5 ml-4" />
                                </button>
                              ) : null}
                            </div>
                          )}

                          <p className="mt-2 text-zinc-400 text-sm">
                            Group · {groupDetails?.participants.length}{" "}
                            participants
                          </p>
                        </div>
                        <hr className="border-[0.1px] border-zinc-600 my-5 w-full" />
                        <div className="w-full">
                          <p className="inline-flex items-center">
                            <UserGroupIcon className="h-6 w-6 mr-2" />{" "}
                            {groupDetails?.participants.length} Participants
                          </p>
                          <div className="w-full">
                            {groupDetails?.participants?.map((part) => {
                              return (
                                <React.Fragment key={part._id}>
                                  <div className="flex justify-between items-center w-full py-4">
                                    <div className="flex justify-start items-start gap-3 w-full">
                                      <img
                                        className="h-12 w-12 rounded-full"
                                        src={part.avatar.url}
                                      />
                                      <div>
                                        <p className="text-white font-semibold text-sm inline-flex items-center w-full">
                                          {part.username}{" "}
                                          {part._id === groupDetails.admin ? (
                                            <span className="ml-2 text-[10px] px-4 bg-success/10 border-[0.1px] border-success rounded-full text-success">
                                              admin
                                            </span>
                                          ) : null}
                                        </p>
                                        <small className="text-zinc-400">
                                          {part.email}
                                        </small>
                                      </div>
                                    </div>
                                    {groupDetails.admin === user?._id ? (
                                      <div>
                                        <Button
                                          onClick={() => {
                                            const ok = confirm(
                                              "Are you sure you want to remove " +
                                                user.username +
                                                " ?"
                                            );
                                            if (ok) {
                                              removeParticipant(part._id || "");
                                            }
                                          }}
                                          size="small"
                                          severity="danger"
                                        >
                                          Remove
                                        </Button>
                                      </div>
                                    ) : null}
                                  </div>
                                  <hr className="border-[0.1px] border-zinc-600 my-1 w-full" />
                                </React.Fragment>
                              );
                            })}
                            {groupDetails?.admin === user?._id ? (
                              <div className="w-full my-5 flex flex-col justify-center items-center gap-4">
                                {!addingParticipant ? (
                                  <Button
                                    onClick={() => setAddingParticipant(true)}
                                    fullWidth
                                    severity="primary"
                                  >
                                    <UserPlusIcon className="w-5 h-5 mr-1" />{" "}
                                    Add participant
                                  </Button>
                                ) : (
                                  <div className="w-full flex justify-start items-center gap-2">
                                    <Select
                                      placeholder="Select a user to add..."
                                      value={participantToBeAdded}
                                      options={users.map((user) => ({
                                        label: user.username,
                                        value: user._id,
                                      }))}
                                      onChange={({ value }) => {
                                        setParticipantToBeAdded(value);
                                      }}
                                    />
                                    <Button onClick={() => addParticipant()}>
                                      + Add
                                    </Button>
                                    <Button
                                      severity="secondary"
                                      onClick={() => {
                                        setAddingParticipant(false);
                                        setParticipantToBeAdded("");
                                      }}
                                    >
                                      Cancel
                                    </Button>
                                  </div>
                                )}
                                <Button
                                  fullWidth
                                  severity="danger"
                                  onClick={() => {
                                    const ok = confirm(
                                      "Are you sure you want to delete this group?"
                                    );
                                    if (ok) {
                                      deleteGroupChat();
                                    }
                                  }}
                                >
                                  <TrashIcon className="w-5 h-5 mr-1" /> Delete
                                  group
                                </Button>
                              </div>
                            ) : null}
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </Dialog.Panel>
              </Transition.Child>
            </div>
          </div>
        </div>
      </Dialog>
    </Transition.Root>
  );
};

export default GroupChatDetailsModal;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/MessageItem.tsx
================================================
import {
  ArrowDownTrayIcon,
  EllipsisVerticalIcon,
  MagnifyingGlassPlusIcon,
  PaperClipIcon,
  TrashIcon,
  XMarkIcon,
} from "@heroicons/react/20/solid";
import moment from "moment";
import { useState } from "react";
import { ChatMessageInterface } from "../../interfaces/chat";
import { classNames } from "../../utils";
const MessageItem: React.FC<{
  isOwnMessage?: boolean;
  isGroupChatMessage?: boolean;
  message: ChatMessageInterface;
  deleteChatMessage: (message: ChatMessageInterface) => void;
}> = ({ message, isOwnMessage, isGroupChatMessage, deleteChatMessage }) => {
  const [resizedImage, setResizedImage] = useState<string | null>(null);
  const [openOptions, setopenOptions] = useState<boolean>(false); //To open delete menu option on hover

  return (
    <>
      {resizedImage ? (
        <div className="h-full z-40 p-8 overflow-hidden w-full absolute inset-0 bg-black/70 flex justify-center items-center">
          <XMarkIcon
            className="absolute top-5 right-5 w-9 h-9 text-white cursor-pointer"
            onClick={() => setResizedImage(null)}
          />
          <img
            className="w-full h-full object-contain"
            src={resizedImage}
            alt="chat image"
          />
        </div>
      ) : null}
      <div
        className={classNames(
          "flex justify-start items-end gap-3 max-w-lg min-w-",
          isOwnMessage ? "ml-auto" : ""
        )}
      >
        <img
          src={message.sender?.avatar?.url}
          className={classNames(
            "h-7 w-7 object-cover rounded-full flex flex-shrink-0",
            isOwnMessage ? "order-2" : "order-1"
          )}
        />
        {/* message box have to add the icon onhover here */}
        <div
          onMouseLeave={() => setopenOptions(false)}
          className={classNames(
            " p-4 rounded-3xl flex flex-col cursor-pointer group hover:bg-secondary",
            isOwnMessage
              ? "order-1 rounded-br-none bg-primary"
              : "order-2 rounded-bl-none bg-secondary"
          )}
        >
          {isGroupChatMessage && !isOwnMessage ? (
            <p
              className={classNames(
                "text-xs font-semibold mb-2",
                ["text-success", "text-danger"][
                  message.sender.username.length % 2
                ]
              )}
            >
              {message.sender?.username}
            </p>
          ) : null}
          {message?.attachments?.length > 0 ? (
            <div>
              {/*The option to delete message will only open in case of own messages*/}
              {isOwnMessage ? (
                <button
                  className="self-center p-1 relative options-button"
                  onClick={() => setopenOptions(!openOptions)}
                >
                  <EllipsisVerticalIcon className="group-hover:w-6 group-hover:opacity-100 w-0 opacity-0 transition-all ease-in-out duration-100 text-zinc-300" />
                  <div
                    className={classNames(
                      "z-30 text-left absolute botom-0 translate-y-1 text-[10px] w-auto bg-dark rounded-2xl p-2 shadow-md border-[1px] border-secondary",
                      openOptions ? "block" : "hidden"
                    )}
                  >
                    <p
                      onClick={(e) => {
                        e.stopPropagation();
                        const ok = confirm(
                          "Are you sure you want to delete this message"
                        );
                        if (ok) {
                          deleteChatMessage(message);
                        }
                      }}
                      role="button"
                      className="border border-red-500 p-4 text-danger rounded-lg w-auto inline-flex items-center hover:bg-secondary"
                    >
                      <TrashIcon className="h-4 w-4 mr-2" />
                      Delete Message
                    </p>
                  </div>
                </button>
              ) : null}

              <div
                className={classNames(
                  "grid max-w-7xl gap-2",
                  message.attachments?.length === 1 ? " grid-cols-1" : "",
                  message.attachments?.length === 2 ? " grid-cols-2" : "",
                  message.attachments?.length >= 3 ? " grid-cols-3" : "",
                  message.content ? "mb-6" : ""
                )}
              >
                {message.attachments?.map((file) => {
                  return (
                    <div
                      key={file._id}
                      className="group relative aspect-square rounded-xl overflow-hidden cursor-pointer"
                    >
                      <button
                        onClick={() => setResizedImage(file.url)}
                        className="absolute inset-0 z-20 flex justify-center items-center w-full gap-2 h-full bg-black/60 group-hover:opacity-100 opacity-0 transition-opacity ease-in-out duration-150"
                      >
                        <MagnifyingGlassPlusIcon className="h-6 w-6 text-white" />
                        <a
                          href={file.url}
                          download
                          onClick={(e) => e.stopPropagation()}
                        >
                          <ArrowDownTrayIcon
                            title="download"
                            className="hover:text-zinc-400 h-6 w-6 text-white cursor-pointer"
                          />
                        </a>
                      </button>
                      <img
                        className="h-full w-full object-cover"
                        src={file.url}
                        alt="msg_img"
                      />
                    </div>
                  );
                })}
              </div>
            </div>
          ) : null}
          {message.content ? (
            <div className="relative flex justify-between">
              {/*The option to delete message will only open in case of own messages*/}
              {isOwnMessage ? (
                <button
                  className="self-center relative options-button"
                  onClick={() => setopenOptions(!openOptions)}
                >
                  <EllipsisVerticalIcon className="group-hover:w-4 group-hover:opacity-100 w-0 opacity-0 transition-all ease-in-out duration-100 text-zinc-300" />
                  <div
                    className={classNames(
                      "delete-menu z-20 text-left -translate-x-24 -translate-y-4 absolute botom-0  text-[10px] w-auto bg-dark rounded-2xl  shadow-md border-[1px] border-secondary",
                      openOptions ? "block" : "hidden"
                    )}
                  >
                    <p
                      onClick={(e) => {
                        e.stopPropagation();
                        const ok = confirm(
                          "Are you sure you want to delete this message"
                        );
                        if (ok) {
                          deleteChatMessage(message);
                        }
                      }}
                      role="button"
                      className=" p-2 text-danger rounded-lg w-auto inline-flex items-center hover:bg-secondary"
                    >
                      <TrashIcon className="h-4 w-auto mr-1" />
                      Delete Message
                    </p>
                  </div>
                </button>
              ) : null}

              <p className="text-sm">{message.content}</p>
            </div>
          ) : null}
          <p
            className={classNames(
              "mt-1.5 self-end text-[10px] inline-flex items-center",
              isOwnMessage ? "text-zinc-50" : "text-zinc-400"
            )}
          >
            {message.attachments?.length > 0 ? (
              <PaperClipIcon className="h-4 w-4 mr-2 " />
            ) : null}
            {moment(message.updatedAt).add("TIME_ZONE", "hours").fromNow(true)}{" "}
            ago
          </p>
        </div>
      </div>
    </>
  );
};

export default MessageItem;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/Typing.tsx
================================================
import { classNames } from "../../utils";

const Typing = () => {
  return (
    <div
      className={classNames(
        "p-5 rounded-3xl bg-secondary w-fit inline-flex gap-1.5"
      )}
    >
      <span className="animation1 mx-[0.5px] h-2 w-2 bg-zinc-300 rounded-full"></span>
      <span className="animation2 mx-[0.5px] h-2 w-2 bg-zinc-300 rounded-full"></span>
      <span className="animation3 mx-[0.5px] h-2 w-2 bg-zinc-300 rounded-full"></span>
    </div>
  );
};

export default Typing;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/context/AuthContext.tsx
================================================
import React, { createContext, useContext, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { loginUser, logoutUser, registerUser } from "../api";
import Loader from "../components/Loader";
import { UserInterface } from "../interfaces/user";
import { LocalStorage, requestHandler } from "../utils";

// Create a context to manage authentication-related data and functions
const AuthContext = createContext<{
  user: UserInterface | null;
  token: string | null;
  login: (data: { username: string; password: string }) => Promise<void>;
  register: (data: {
    email: string;
    username: string;
    password: string;
  }) => Promise<void>;
  logout: () => Promise<void>;
}>({
  user: null,
  token: null,
  login: async () => {},
  register: async () => {},
  logout: async () => {},
});

// Create a hook to access the AuthContext
const useAuth = () => useContext(AuthContext);

// Create a component that provides authentication-related data and functions
const AuthProvider: React.FC<{ children: React.ReactNode }> = ({
  children,
}) => {
  const [isLoading, setIsLoading] = useState(false);
  const [user, setUser] = useState<UserInterface | null>(null);
  const [token, setToken] = useState<string | null>(null);

  const navigate = useNavigate();

  // Function to handle user login
  const login = async (data: { username: string; password: string }) => {
    await requestHandler(
      async () => await loginUser(data),
      setIsLoading,
      (res) => {
        const { data } = res;
        setUser(data.user);
        setToken(data.accessToken);
        LocalStorage.set("user", data.user);
        LocalStorage.set("token", data.accessToken);
        navigate("/chat"); // Redirect to the chat page after successful login
      },
      alert // Display error alerts on request failure
    );
  };

  // Function to handle user registration
  const register = async (data: {
    email: string;
    username: string;
    password: string;
  }) => {
    await requestHandler(
      async () => await registerUser(data),
      setIsLoading,
      () => {
        alert("Account created successfully! Go ahead and login.");
        navigate("/login"); // Redirect to the login page after successful registration
      },
      alert // Display error alerts on request failure
    );
  };

  // Function to handle user logout
  const logout = async () => {
    await requestHandler(
      async () => await logoutUser(),
      setIsLoading,
      () => {
        setUser(null);
        setToken(null);
        LocalStorage.clear(); // Clear local storage on logout
        navigate("/login"); // Redirect to the login page after successful logout
      },
      alert // Display error alerts on request failure
    );
  };

  // Check for saved user and token in local storage during component initialization
  useEffect(() => {
    setIsLoading(true);
    const _token = LocalStorage.get("token");
    const _user = LocalStorage.get("user");
    if (_token && _user?._id) {
      setUser(_user);
      setToken(_token);
    }
    setIsLoading(false);
  }, []);

  // Provide authentication-related data and functions through the context
  return (
    <AuthContext.Provider value={{ user, login, register, logout, token }}>
      {isLoading ? <Loader /> : children} {/* Display a loader while loading */}
    </AuthContext.Provider>
  );
};

// Export the context, provider component, and custom hook
export { AuthContext, AuthProvider, useAuth };


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/context/SocketContext.tsx
================================================
/* eslint-disable react-refresh/only-export-components */
import React, { createContext, useContext, useEffect, useState } from "react";
import socketio from "socket.io-client";
import { LocalStorage } from "../utils";

// Function to establish a socket connection with authorization token
const getSocket = () => {
  const token = LocalStorage.get("token"); // Retrieve jwt token from local storage or cookie

  // Create a socket connection with the provided URI and authentication
  return socketio(import.meta.env.VITE_SOCKET_URI, {
    withCredentials: true,
    auth: { token },
  });
};

// Create a context to hold the socket instance
const SocketContext = createContext<{
  socket: ReturnType<typeof socketio> | null;
}>({
  socket: null,
});

// Custom hook to access the socket instance from the context
const useSocket = () => useContext(SocketContext);

// SocketProvider component to manage the socket instance and provide it through context
const SocketProvider: React.FC<{ children: React.ReactNode }> = ({
  children,
}) => {
  // State to store the socket instance
  const [socket, setSocket] = useState<ReturnType<typeof socketio> | null>(
    null
  );

  // Set up the socket connection when the component mounts
  useEffect(() => {
    setSocket(getSocket());
  }, []);

  return (
    // Provide the socket instance through context to its children
    <SocketContext.Provider value={{ socket }}>
      {children}
    </SocketContext.Provider>
  );
};

// Export the SocketProvider component and the useSocket hook for other components to use
export { SocketProvider, useSocket };


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/index.css
================================================
@import url("https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");

@tailwind base;
@tailwind components;
@tailwind utilities;

* {
  font-family: "Archivo", sans-serif;
}

.truncate-1 {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  line-clamp: 1;
  -webkit-box-orient: vertical;
  line-break: anywhere;
}

@keyframes bounce {
  0% {
    transform: translateY(-60%);
    opacity: 0.7;
  }
  100% {
    transform: translateY(20%);
    opacity: 1;
  }
}

.animation1 {
  animation: bounce 0.4s ease-in-out infinite alternate;
  animation-delay: -0.4s;
}

.animation2 {
  animation: bounce 0.4s ease-in-out infinite alternate;
  animation-delay: -0.2s;
}

.animation3 {
  animation: bounce 0.4s ease-in-out infinite alternate;
  animation-delay: 0s;
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/api.ts
================================================
export interface FreeAPISuccessResponseInterface {
  data: any;
  message: string;
  statusCode: number;
  success: boolean;
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/chat.ts
================================================
import { UserInterface } from "./user";

export interface ChatListItemInterface {
  admin: string;
  createdAt: string;
  isGroupChat: true;
  lastMessage?: ChatMessageInterface;
  name: string;
  participants: UserInterface[];
  updatedAt: string;
  _id: string;
}

export interface ChatMessageInterface {
  _id: string;
  sender: Pick<UserInterface, "_id" | "avatar" | "email" | "username">;
  content: string;
  chat: string;
  attachments: {
    url: string;
    localPath: string;
    _id: string;
  }[];
  createdAt: string;
  updatedAt: string;
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/user.ts
================================================
export interface UserInterface {
  _id: string;
  avatar: {
    url: string;
    localPath: string;
    _id: string;
  };
  username: string;
  email: string;
  createdAt: string;
  updatedAt: string;
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/main.tsx
================================================
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { AuthProvider } from "./context/AuthContext.tsx";
import { BrowserRouter } from "react-router-dom";
import { SocketProvider } from "./context/SocketContext.tsx";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <BrowserRouter>
      <AuthProvider>
        <SocketProvider>
          <App />
        </SocketProvider>
      </AuthProvider>
    </BrowserRouter>
  </React.StrictMode>
);


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/pages/chat.tsx
================================================
import {
  PaperAirplaneIcon,
  PaperClipIcon,
  XCircleIcon,
} from "@heroicons/react/20/solid";
import { useEffect, useRef, useState } from "react";
import {
  deleteMessage,
  getChatMessages,
  getUserChats,
  sendMessage,
} from "../api";
import AddChatModal from "../components/chat/AddChatModal";
import ChatItem from "../components/chat/ChatItem";
import MessageItem from "../components/chat/MessageItem";
import Typing from "../components/chat/Typing";
import Input from "../components/Input";
import { useAuth } from "../context/AuthContext";
import { useSocket } from "../context/SocketContext";
import {
  ChatListItemInterface,
  ChatMessageInterface,
} from "../interfaces/chat";
import {
  LocalStorage,
  classNames,
  getChatObjectMetadata,
  requestHandler,
} from "../utils";

const CONNECTED_EVENT = "connected";
const DISCONNECT_EVENT = "disconnect";
const JOIN_CHAT_EVENT = "joinChat";
const NEW_CHAT_EVENT = "newChat";
const TYPING_EVENT = "typing";
const STOP_TYPING_EVENT = "stopTyping";
const MESSAGE_RECEIVED_EVENT = "messageReceived";
const LEAVE_CHAT_EVENT = "leaveChat";
const UPDATE_GROUP_NAME_EVENT = "updateGroupName";
const MESSAGE_DELETE_EVENT = "messageDeleted";
// const SOCKET_ERROR_EVENT = "socketError";

const ChatPage = () => {
  // Import the 'useAuth' and 'useSocket' hooks from their respective contexts
  const { user, logout } = useAuth();
  const { socket } = useSocket();

  // Create a reference using 'useRef' to hold the currently selected chat.
  // 'useRef' is used here because it ensures that the 'currentChat' value within socket event callbacks
  // will always refer to the latest value, even if the component re-renders.
  const currentChat = useRef<ChatListItemInterface | null>(null);

  // To keep track of the setTimeout function
  const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Define state variables and their initial values using 'useState'
  const [isConnected, setIsConnected] = useState(false); // For tracking socket connection

  const [openAddChat, setOpenAddChat] = useState(false); // To control the 'Add Chat' modal
  const [loadingChats, setLoadingChats] = useState(false); // To indicate loading of chats
  const [loadingMessages, setLoadingMessages] = useState(false); // To indicate loading of messages

  const [chats, setChats] = useState<ChatListItemInterface[]>([]); // To store user's chats
  const [messages, setMessages] = useState<ChatMessageInterface[]>([]); // To store chat messages
  const [unreadMessages, setUnreadMessages] = useState<ChatMessageInterface[]>(
    []
  ); // To track unread messages

  const [isTyping, setIsTyping] = useState(false); // To track if someone is currently typing
  const [selfTyping, setSelfTyping] = useState(false); // To track if the current user is typing

  const [message, setMessage] = useState(""); // To store the currently typed message
  const [localSearchQuery, setLocalSearchQuery] = useState(""); // For local search functionality

  const [attachedFiles, setAttachedFiles] = useState<File[]>([]); // To store files attached to messages

  /**
   *  A  function to update the last message of a specified chat to update the chat list
   */
  const updateChatLastMessage = (
    chatToUpdateId: string,
    message: ChatMessageInterface // The new message to be set as the last message
  ) => {
    // Search for the chat with the given ID in the chats array
    const chatToUpdate = chats.find((chat) => chat._id === chatToUpdateId)!;

    // Update the 'lastMessage' field of the found chat with the new message
    chatToUpdate.lastMessage = message;

    // Update the 'updatedAt' field of the chat with the 'updatedAt' field from the message
    chatToUpdate.updatedAt = message?.updatedAt;

    // Update the state of chats, placing the updated chat at the beginning of the array
    setChats([
      chatToUpdate, // Place the updated chat first
      ...chats.filter((chat) => chat._id !== chatToUpdateId), // Include all other chats except the updated one
    ]);
  };
  /**
   *A function to update the chats last message specifically in case of deletion of message *
   **/

  const updateChatLastMessageOnDeletion = (
    chatToUpdateId: string, //ChatId to find the chat
    message: ChatMessageInterface //The deleted message
  ) => {
    // Search for the chat with the given ID in the chats array
    const chatToUpdate = chats.find((chat) => chat._id === chatToUpdateId)!;

    //Updating the last message of chat only in case of deleted message and chats last message is same
    if (chatToUpdate.lastMessage?._id === message._id) {
      requestHandler(
        async () => getChatMessages(chatToUpdateId),
        null,
        (req) => {
          const { data } = req;

          chatToUpdate.lastMessage = data[0];
          setChats([...chats]);
        },
        alert
      );
    }
  };
  const getChats = async () => {
    requestHandler(
      async () => await getUserChats(),
      setLoadingChats,
      (res) => {
        const { data } = res;
        setChats(data || []);
      },
      alert
    );
  };

  const getMessages = async () => {
    // Check if a chat is selected, if not, show an alert
    if (!currentChat.current?._id) return alert("No chat is selected");

    // Check if socket is available, if not, show an alert
    if (!socket) return alert("Socket not available");

    // Emit an event to join the current chat
    socket.emit(JOIN_CHAT_EVENT, currentChat.current?._id);

    // Filter out unread messages from the current chat as those will be read
    setUnreadMessages(
      unreadMessages.filter((msg) => msg.chat !== currentChat.current?._id)
    );

    // Make an async request to fetch chat messages for the current chat
    requestHandler(
      // Fetching messages for the current chat
      async () => await getChatMessages(currentChat.current?._id || ""),
      // Set the state to loading while fetching the messages
      setLoadingMessages,
      // After fetching, set the chat messages to the state if available
      (res) => {
        const { data } = res;
        setMessages(data || []);
      },
      // Display any error alerts if they occur during the fetch
      alert
    );
  };

  // Function to send a chat message
  const sendChatMessage = async () => {
    // If no current chat ID exists or there's no socket connection, exit the function
    if (!currentChat.current?._id || !socket) return;

    // Emit a STOP_TYPING_EVENT to inform other users/participants that typing has stopped
    socket.emit(STOP_TYPING_EVENT, currentChat.current?._id);

    // Use the requestHandler to send the message and handle potential response or error
    await requestHandler(
      // Try to send the chat message with the given message and attached files
      async () =>
        await sendMessage(
          currentChat.current?._id || "", // Chat ID or empty string if not available
          message, // Actual text message
          attachedFiles // Any attached files
        ),
      null,
      // On successful message sending, clear the message input and attached files, then update the UI
      (res) => {
        setMessage(""); // Clear the message input
        setAttachedFiles([]); // Clear the list of attached files
        setMessages((prev) => [res.data, ...prev]); // Update messages in the UI
        updateChatLastMessage(currentChat.current?._id || "", res.data); // Update the last message in the chat
      },

      // If there's an error during the message sending process, raise an alert
      alert
    );
  };
  const deleteChatMessage = async (message: ChatMessageInterface) => {
    //ONClick delete the message and reload the chat when deleteMessage socket gives any response in chat.tsx
    //use request handler to prevent any errors

    await requestHandler(
      async () => await deleteMessage(message.chat, message._id),
      null,
      (res) => {
        setMessages((prev) => prev.filter((msg) => msg._id !== res.data._id));
        updateChatLastMessageOnDeletion(message.chat, message);
      },
      alert
    );
  };

  const handleOnMessageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // Update the message state with the current input value
    setMessage(e.target.value);

    // If socket doesn't exist or isn't connected, exit the function
    if (!socket || !isConnected) return;

    // Check if the user isn't already set as typing
    if (!selfTyping) {
      // Set the user as typing
      setSelfTyping(true);

      // Emit a typing event to the server for the current chat
      socket.emit(TYPING_EVENT, currentChat.current?._id);
    }

    // Clear the previous timeout (if exists) to avoid multiple setTimeouts from running
    if (typingTimeoutRef.current) {
      clearTimeout(typingTimeoutRef.current);
    }

    // Define a length of time (in milliseconds) for the typing timeout
    const timerLength = 3000;

    // Set a timeout to stop the typing indication after the timerLength has passed
    typingTimeoutRef.current = setTimeout(() => {
      // Emit a stop typing event to the server for the current chat
      socket.emit(STOP_TYPING_EVENT, currentChat.current?._id);

      // Reset the user's typing state
      setSelfTyping(false);
    }, timerLength);
  };

  const onConnect = () => {
    setIsConnected(true);
  };

  const onDisconnect = () => {
    setIsConnected(false);
  };

  /**
   * Handles the "typing" event on the socket.
   */
  const handleOnSocketTyping = (chatId: string) => {
    // Check if the typing event is for the currently active chat.
    if (chatId !== currentChat.current?._id) return;

    // Set the typing state to true for the current chat.
    setIsTyping(true);
  };

  /**
   * Handles the "stop typing" event on the socket.
   */
  const handleOnSocketStopTyping = (chatId: string) => {
    // Check if the stop typing event is for the currently active chat.
    if (chatId !== currentChat.current?._id) return;

    // Set the typing state to false for the current chat.
    setIsTyping(false);
  };

  const onMessageDelete = (message: ChatMessageInterface) => {
    if (message?.chat !== currentChat.current?._id) {
      setUnreadMessages((prev) =>
        prev.filter((msg) => msg._id !== message._id)
      );
    } else {
      setMessages((prev) => prev.filter((msg) => msg._id !== message._id));
    }

    updateChatLastMessageOnDeletion(message.chat, message);
  };

  /**
   * Handles the event when a new message is received.
   */
  const onMessageReceived = (message: ChatMessageInterface) => {
    // Check if the received message belongs to the currently active chat
    if (message?.chat !== currentChat.current?._id) {
      // If not, update the list of unread messages
      setUnreadMessages((prev) => [message, ...prev]);
    } else {
      // If it belongs to the current chat, update the messages list for the active chat
      setMessages((prev) => [message, ...prev]);
    }

    // Update the last message for the chat to which the received message belongs
    updateChatLastMessage(message.chat || "", message);
  };

  const onNewChat = (chat: ChatListItemInterface) => {
    setChats((prev) => [chat, ...prev]);
  };

  // This function handles the event when a user leaves a chat.
  const onChatLeave = (chat: ChatListItemInterface) => {
    // Check if the chat the user is leaving is the current active chat.
    if (chat._id === currentChat.current?._id) {
      // If the user is in the group chat they're leaving, close the chat window.
      currentChat.current = null;
      // Remove the currentChat from local storage.
      LocalStorage.remove("currentChat");
    }
    // Update the chats by removing the chat that the user left.
    setChats((prev) => prev.filter((c) => c._id !== chat._id));
  };

  // Function to handle changes in group name
  const onGroupNameChange = (chat: ChatListItemInterface) => {
    // Check if the chat being changed is the currently active chat
    if (chat._id === currentChat.current?._id) {
      // Update the current chat with the new details
      currentChat.current = chat;

      // Save the updated chat details to local storage
      LocalStorage.set("currentChat", chat);
    }

    // Update the list of chats with the new chat details
    setChats((prev) => [
      // Map through the previous chats
      ...prev.map((c) => {
        // If the current chat in the map matches the chat being changed, return the updated chat
        if (c._id === chat._id) {
          return chat;
        }
        // Otherwise, return the chat as-is without any changes
        return c;
      }),
    ]);
  };

  useEffect(() => {
    // Fetch the chat list from the server.
    getChats();

    // Retrieve the current chat details from local storage.
    const _currentChat = LocalStorage.get("currentChat");

    // If there's a current chat saved in local storage:
    if (_currentChat) {
      // Set the current chat reference to the one from local storage.
      currentChat.current = _currentChat;
      // If the socket connection exists, emit an event to join the specific chat using its ID.
      socket?.emit(JOIN_CHAT_EVENT, _currentChat.current?._id);
      // Fetch the messages for the current chat.
      getMessages();
    }
    // An empty dependency array ensures this useEffect runs only once, similar to componentDidMount.
  }, []);

  // This useEffect handles the setting up and tearing down of socket event listeners.
  useEffect(() => {
    // If the socket isn't initialized, we don't set up listeners.
    if (!socket) return;

    // Set up event listeners for various socket events:
    // Listener for when the socket connects.
    socket.on(CONNECTED_EVENT, onConnect);
    // Listener for when the socket disconnects.
    socket.on(DISCONNECT_EVENT, onDisconnect);
    // Listener for when a user is typing.
    socket.on(TYPING_EVENT, handleOnSocketTyping);
    // Listener for when a user stops typing.
    socket.on(STOP_TYPING_EVENT, handleOnSocketStopTyping);
    // Listener for when a new message is received.
    socket.on(MESSAGE_RECEIVED_EVENT, onMessageReceived);
    // Listener for the initiation of a new chat.
    socket.on(NEW_CHAT_EVENT, onNewChat);
    // Listener for when a user leaves a chat.
    socket.on(LEAVE_CHAT_EVENT, onChatLeave);
    // Listener for when a group's name is updated.
    socket.on(UPDATE_GROUP_NAME_EVENT, onGroupNameChange);
    //Listener for when a message is deleted
    socket.on(MESSAGE_DELETE_EVENT, onMessageDelete);
    // When the component using this hook unmounts or if `socket` or `chats` change:
    return () => {
      // Remove all the event listeners we set up to avoid memory leaks and unintended behaviors.
      socket.off(CONNECTED_EVENT, onConnect);
      socket.off(DISCONNECT_EVENT, onDisconnect);
      socket.off(TYPING_EVENT, handleOnSocketTyping);
      socket.off(STOP_TYPING_EVENT, handleOnSocketStopTyping);
      socket.off(MESSAGE_RECEIVED_EVENT, onMessageReceived);
      socket.off(NEW_CHAT_EVENT, onNewChat);
      socket.off(LEAVE_CHAT_EVENT, onChatLeave);
      socket.off(UPDATE_GROUP_NAME_EVENT, onGroupNameChange);
      socket.off(MESSAGE_DELETE_EVENT, onMessageDelete);
    };

    // Note:
    // The `chats` array is used in the `onMessageReceived` function.
    // We need the latest state value of `chats`. If we don't pass `chats` in the dependency array,
    // the `onMessageReceived` will consider the initial value of the `chats` array, which is empty.
    // This will not cause infinite renders because the functions in the socket are getting mounted and not executed.
    // So, even if some socket callbacks are updating the `chats` state, it's not
    // updating on each `useEffect` call but on each socket call.
  }, [socket, chats]);

  return (
    <>
      <AddChatModal
        open={openAddChat}
        onClose={() => {
          setOpenAddChat(false);
        }}
        onSuccess={() => {
          getChats();
        }}
      />

      <div className="w-full justify-between items-stretch h-screen flex flex-shrink-0">
        <div className="w-1/3 relative ring-white overflow-y-auto px-4">
          <div className="z-10 w-full sticky top-0 bg-dark py-4 flex justify-between items-center gap-4">
            <button
              type="button"
              className="focus:outline-none text-white bg-purple-700 hover:bg-purple-800 focus:ring-4 focus:ring-purple-300 font-medium rounded-xl text-sm px-5 py-4 mb-2 dark:bg-purple-600 dark:hover:bg-purple-700 dark:focus:ring-purple-900 flex-shrink-0"
              onClick={logout}
            >
              Log Out
            </button>

            <Input
              placeholder="Search user or group..."
              value={localSearchQuery}
              onChange={(e) =>
                setLocalSearchQuery(e.target.value.toLowerCase())
              }
            />
            <button
              onClick={() => setOpenAddChat(true)}
              className="rounded-xl border-none bg-primary text-white py-4 px-5 flex flex-shrink-0"
            >
              + Add chat
            </button>
          </div>
          {loadingChats ? (
            <div className="flex justify-center items-center h-[calc(100%-88px)]">
              <Typing />
            </div>
          ) : (
            // Iterating over the chats array
            [...chats]
              // Filtering chats based on a local search query
              .filter((chat) =>
                // If there's a localSearchQuery, filter chats that contain the query in their metadata title
                localSearchQuery
                  ? getChatObjectMetadata(chat, user!)
                      .title?.toLocaleLowerCase()
                      ?.includes(localSearchQuery)
                  : // If there's no localSearchQuery, include all chats
                    true
              )
              .map((chat) => {
                return (
                  <ChatItem
                    chat={chat}
                    isActive={chat._id === currentChat.current?._id}
                    unreadCount={
                      unreadMessages.filter((n) => n.chat === chat._id).length
                    }
                    onClick={(chat) => {
                      if (
                        currentChat.current?._id &&
                        currentChat.current?._id === chat._id
                      )
                        return;
                      LocalStorage.set("currentChat", chat);
                      currentChat.current = chat;
                      setMessage("");
                      getMessages();
                    }}
                    key={chat._id}
                    onChatDelete={(chatId) => {
                      setChats((prev) =>
                        prev.filter((chat) => chat._id !== chatId)
                      );
                      if (currentChat.current?._id === chatId) {
                        currentChat.current = null;
                        LocalStorage.remove("currentChat");
                      }
                    }}
                  />
                );
              })
          )}
        </div>
        <div className="w-2/3 border-l-[0.1px] border-secondary">
          {currentChat.current && currentChat.current?._id ? (
            <>
              <div className="p-4 sticky top-0 bg-dark z-20 flex justify-between items-center w-full border-b-[0.1px] border-secondary">
                <div className="flex justify-start items-center w-max gap-3">
                  {currentChat.current.isGroupChat ? (
                    <div className="w-12 relative h-12 flex-shrink-0 flex justify-start items-center flex-nowrap">
                      {currentChat.current.participants
                        .slice(0, 3)
                        .map((participant, i) => {
                          return (
                            <img
                              key={participant._id}
                              src={participant.avatar.url}
                              className={classNames(
                                "w-9 h-9 border-[1px] border-white rounded-full absolute outline outline-4 outline-dark",
                                i === 0
                                  ? "left-0 z-30"
                                  : i === 1
                                  ? "left-2 z-20"
                                  : i === 2
                                  ? "left-4 z-10"
                                  : ""
                              )}
                            />
                          );
                        })}
                    </div>
                  ) : (
                    <img
                      className="h-14 w-14 rounded-full flex flex-shrink-0 object-cover"
                      src={
                        getChatObjectMetadata(currentChat.current, user!).avatar
                      }
                    />
                  )}
                  <div>
                    <p className="font-bold">
                      {getChatObjectMetadata(currentChat.current, user!).title}
                    </p>
                    <small className="text-zinc-400">
                      {
                        getChatObjectMetadata(currentChat.current, user!)
                          .description
                      }
                    </small>
                  </div>
                </div>
              </div>
              <div
                className={classNames(
                  "p-8 overflow-y-auto flex flex-col-reverse gap-6 w-full",
                  attachedFiles.length > 0
                    ? "h-[calc(100vh-336px)]"
                    : "h-[calc(100vh-176px)]"
                )}
                id="message-window"
              >
                {loadingMessages ? (
                  <div className="flex justify-center items-center h-[calc(100%-88px)]">
                    <Typing />
                  </div>
                ) : (
                  <>
                    {isTyping ? <Typing /> : null}
                    {messages?.map((msg) => {
                      return (
                        <MessageItem
                          key={msg._id}
                          isOwnMessage={msg.sender?._id === user?._id}
                          isGroupChatMessage={currentChat.current?.isGroupChat}
                          message={msg}
                          deleteChatMessage={deleteChatMessage}
                        />
                      );
                    })}
                  </>
                )}
              </div>
              {attachedFiles.length > 0 ? (
                <div className="grid gap-4 grid-cols-5 p-4 justify-start max-w-fit">
                  {attachedFiles.map((file, i) => {
                    return (
                      <div
                        key={i}
                        className="group w-32 h-32 relative aspect-square rounded-xl cursor-pointer"
                      >
                        <div className="absolute inset-0 flex justify-center items-center w-full h-full bg-black/40 group-hover:opacity-100 opacity-0 transition-opacity ease-in-out duration-150">
                          <button
                            onClick={() => {
                              setAttachedFiles(
                                attachedFiles.filter((_, ind) => ind !== i)
                              );
                            }}
                            className="absolute -top-2 -right-2"
                          >
                            <XCircleIcon className="h-6 w-6 text-white" />
                          </button>
                        </div>
                        <img
                          className="h-full rounded-xl w-full object-cover"
                          src={URL.createObjectURL(file)}
                          alt="attachment"
                        />
                      </div>
                    );
                  })}
                </div>
              ) : null}
              <div className="sticky top-full p-4 flex justify-between items-center w-full gap-2 border-t-[0.1px] border-secondary">
                <input
                  hidden
                  id="attachments"
                  type="file"
                  value=""
                  multiple
                  max={5}
                  onChange={(e) => {
                    if (e.target.files) {
                      setAttachedFiles([...e.target.files]);
                    }
                  }}
                />
                <label
                  htmlFor="attachments"
                  className="p-4 rounded-full bg-dark hover:bg-secondary"
                >
                  <PaperClipIcon className="w-6 h-6" />
                </label>

                <Input
                  placeholder="Message"
                  value={message}
                  onChange={handleOnMessageChange}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") {
                      sendChatMessage();
                    }
                  }}
                />
                <button
                  onClick={sendChatMessage}
                  disabled={!message && attachedFiles.length <= 0}
                  className="p-4 rounded-full bg-dark hover:bg-secondary disabled:opacity-50"
                >
                  <PaperAirplaneIcon className="w-6 h-6" />
                </button>
              </div>
            </>
          ) : (
            <div className="w-full h-full flex justify-center items-center">
              No chat selected
            </div>
          )}
        </div>
      </div>
    </>
  );
};

export default ChatPage;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/pages/login.tsx
================================================
// Importing necessary components and hooks
import { LockClosedIcon } from "@heroicons/react/20/solid";
import { useState } from "react";
import Button from "../components/Button";
import Input from "../components/Input";
import { useAuth } from "../context/AuthContext";

// Component for the Login page
const Login = () => {
  // State to manage input data (username and password)
  const [data, setData] = useState({
    username: "",
    password: "",
  });

  // Accessing the login function from the AuthContext
  const { login } = useAuth();

  // Function to update state when input data changes
  const handleDataChange =
    (name: string) => (e: React.ChangeEvent<HTMLInputElement>) => {
      setData({
        ...data,
        [name]: e.target.value,
      });
    };

  // Function to handle the login process
  const handleLogin = async () => await login(data);

  return (
    <div className="flex justify-center items-center flex-col h-screen w-screen">
      <h1 className="text-3xl font-bold">FreeAPI Chat App</h1>
      <div className="max-w-5xl w-1/2 p-8 flex justify-center items-center gap-5 flex-col bg-dark shadow-md rounded-2xl my-16 border-secondary border-[1px]">
        <h1 className="inline-flex items-center text-2xl mb-4 flex-col">
          <LockClosedIcon className="h-8 w-8 mb-2" /> Login
        </h1>
        {/* Input for entering the username */}
        <Input
          placeholder="Enter the username..."
          value={data.username}
          onChange={handleDataChange("username")}
        />
        {/* Input for entering the password */}
        <Input
          placeholder="Enter the password..."
          type="password"
          value={data.password}
          onChange={handleDataChange("password")}
        />
        {/* Button to initiate the login process */}
        <Button
          disabled={Object.values(data).some((val) => !val)}
          fullWidth
          onClick={handleLogin}
        >
          Login
        </Button>
        {/* Link to the registration page */}
        <small className="text-zinc-300">
          Don&apos;t have an account?{" "}
          <a className="text-primary hover:underline" href="/register">
            Register
          </a>
        </small>
      </div>
    </div>
  );
};

export default Login;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/pages/register.tsx
================================================
// Import necessary components and hooks
import { LockClosedIcon } from "@heroicons/react/20/solid";
import { useState } from "react";
import Button from "../components/Button";
import Input from "../components/Input";
import { useAuth } from "../context/AuthContext";

// Component for user registration
const Register = () => {
  // State to manage user registration data
  const [data, setData] = useState({
    email: "",
    username: "",
    password: "",
  });

  // Access the register function from the authentication context
  const { register } = useAuth();

  // Handle data change for input fields
  const handleDataChange =
    (name: string) => (e: React.ChangeEvent<HTMLInputElement>) => {
      // Update the corresponding field in the data state
      setData({
        ...data,
        [name]: e.target.value,
      });
    };

  // Handle user registration
  const handleRegister = async () => await register(data);

  return (
    // Register form UI
    <div className="flex justify-center items-center flex-col h-screen w-screen">
      <h1 className="text-3xl font-bold">FreeAPI Chat App</h1>
      <div className="max-w-5xl w-1/2 p-8 flex justify-center items-center gap-5 flex-col bg-dark shadow-md rounded-2xl my-16 border-secondary border-[1px]">
        <h1 className="inline-flex items-center text-2xl mb-4 flex-col">
          {/* Lock icon */}
          <LockClosedIcon className="h-8 w-8 mb-2" /> Register
        </h1>
        {/* Input fields for username, password, and email */}
        <Input
          placeholder="Enter the email..."
          type="email"
          value={data.email}
          onChange={handleDataChange("email")}
        />
        <Input
          placeholder="Enter the username..."
          value={data.username}
          onChange={handleDataChange("username")}
        />
        <Input
          placeholder="Enter the password..."
          type="password"
          value={data.password}
          onChange={handleDataChange("password")}
        />
        {/* Register button */}
        <Button
          fullWidth
          disabled={Object.values(data).some((val) => !val)}
          onClick={handleRegister}
        >
          Register
        </Button>
        {/* Login link */}
        <small className="text-zinc-300">
          Already have an account?{" "}
          <a className="text-primary hover:underline" href="/login">
            Login
          </a>
        </small>
      </div>
    </div>
  );
};

export default Register;


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/utils/index.ts
================================================
// Importing necessary modules and interfaces
import { AxiosResponse } from "axios";
import { FreeAPISuccessResponseInterface } from "../interfaces/api";
import { ChatListItemInterface } from "../interfaces/chat";
import { UserInterface } from "../interfaces/user";

// A utility function for handling API requests with loading, success, and error handling
export const requestHandler = async (
  api: () => Promise<AxiosResponse<FreeAPISuccessResponseInterface, any>>,
  setLoading: ((loading: boolean) => void) | null,
  onSuccess: (data: FreeAPISuccessResponseInterface) => void,
  onError: (error: string) => void
) => {
  // Show loading state if setLoading function is provided
  setLoading && setLoading(true);
  try {
    // Make the API request
    const response = await api();
    const { data } = response;
    if (data?.success) {
      // Call the onSuccess callback with the response data
      onSuccess(data);
    }
  } catch (error: any) {
    // Handle error cases, including unauthorized and forbidden cases
    if ([401, 403].includes(error?.response.data?.statusCode)) {
      localStorage.clear(); // Clear local storage on authentication issues
      if (isBrowser) window.location.href = "/login"; // Redirect to login page
    }
    onError(error?.response?.data?.message || "Something went wrong");
  } finally {
    // Hide loading state if setLoading function is provided
    setLoading && setLoading(false);
  }
};

// A utility function to concatenate CSS class names with proper spacing
export const classNames = (...className: string[]) => {
  // Filter out any empty class names and join them with a space
  return className.filter(Boolean).join(" ");
};

// Check if the code is running in a browser environment
export const isBrowser = typeof window !== "undefined";

// This utility function generates metadata for chat objects.
// It takes into consideration both group chats and individual chats.
export const getChatObjectMetadata = (
  chat: ChatListItemInterface, // The chat item for which metadata is being generated.
  loggedInUser: UserInterface // The currently logged-in user details.
) => {
  // Determine the content of the last message, if any.
  // If the last message contains only attachments, indicate their count.
  const lastMessage = chat.lastMessage?.content
    ? chat.lastMessage?.content
    : chat.lastMessage
    ? `${chat.lastMessage?.attachments?.length} attachment${
        chat.lastMessage.attachments.length > 1 ? "s" : ""
      }`
    : "No messages yet"; // Placeholder text if there are no messages.

  if (chat.isGroupChat) {
    // Case: Group chat
    // Return metadata specific to group chats.
    return {
      // Default avatar for group chats.
      avatar: "https://via.placeholder.com/100x100.png",
      title: chat.name, // Group name serves as the title.
      description: `${chat.participants.length} members in the chat`, // Description indicates the number of members.
      lastMessage: chat.lastMessage
        ? chat.lastMessage?.sender?.username + ": " + lastMessage
        : lastMessage,
    };
  } else {
    // Case: Individual chat
    // Identify the participant other than the logged-in user.
    const participant = chat.participants.find(
      (p) => p._id !== loggedInUser?._id
    );
    // Return metadata specific to individual chats.
    return {
      avatar: participant?.avatar.url, // Participant's avatar URL.
      title: participant?.username, // Participant's username serves as the title.
      description: participant?.email, // Email address of the participant.
      lastMessage,
    };
  }
};

// A class that provides utility functions for working with local storage
export class LocalStorage {
  // Get a value from local storage by key
  static get(key: string) {
    if (!isBrowser) return;
    const value = localStorage.getItem(key);
    if (value) {
      try {
        return JSON.parse(value);
      } catch (err) {
        return null;
      }
    }
    return null;
  }

  // Set a value in local storage by key
  static set(key: string, value: any) {
    if (!isBrowser) return;
    localStorage.setItem(key, JSON.stringify(value));
  }

  // Remove a value from local storage by key
  static remove(key: string) {
    if (!isBrowser) return;
    localStorage.removeItem(key);
  }

  // Clear all items from local storage
  static clear() {
    if (!isBrowser) return;
    localStorage.clear();
  }
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/src/vite-env.d.ts
================================================
/// <reference types="vite/client" />


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/tailwind.config.js
================================================
/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {
      colors: {
        primary: "#6b8afd",
        secondary: "#2e333d",
        dark: "#212328",
        danger: "#eb3330",
        success: "#4aac68",
      },
    },
  },
  plugins: [],
};


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/tsconfig.node.json
================================================
{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}


================================================
FILE: examples/apps/chat-app/web/react-vite-tailwind/vite.config.ts
================================================
import { defineConfig } from "vite";
import dns from "dns";
import react from "@vitejs/plugin-react";

dns.setDefaultResultOrder("verbatim");

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    host: "localhost",
    port: 3000,
  },
});


================================================
FILE: examples/apps/ecommerce/.gitkeep
================================================


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/.eslintrc.cjs
================================================
module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
  ],
  ignorePatterns: ['dist', '.eslintrc.cjs'],
  parser: '@typescript-eslint/parser',
  plugins: ['react-refresh'],
  rules: {
    'react-refresh/only-export-components': [
      'warn',
      { allowConstantExport: true },
    ],
  },
}


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/.gitignore
================================================
.env
server
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/README.md
================================================
## ecommerce frontend application

This is an ecommerce client app which is made by consuming freeapi: https://github.com/hiteshchoudhary/apihub.

### Steps to run the code locally
* Download the freeapi project from: https://github.com/hiteshchoudhary/apihub, and set the project up.
    * Make sure to configure the following:
        * **CORS_ORIGIN as the exact frontend endpoint**.
        * MAILTRAP credentials for emails. (Used in forgot password feature)
        * Paypal Client ID and Client Secret.
        * Google SSO Credentials for logging in with google.
        * In .env, Set CLIENT_SSO_REDIRECT_URL to <FRONT_END_ENDPOINT>/ for redirects after logging in from google. example http://localhost:3000/
    * Update the following in the freeapi project:
        * Add an environment variable in .env file for forgot password redirection, and point it to the <FRONT_END_ENDPOINT>/forgot-password, as follows: 
          ```FORGOT_PASSWORD_REDIRECT_URL=http://localhost:3000/forgot-password```
        * In src/controllers/apps/auth/user.controller.js file, Update the forgot password controller to use the above environment variable when sending an email
          by using ```${process.env.FORGOT_PASSWORD_REDIRECT_URL}/${unHashedToken}``` when calling the sendEmail function inside the controller.
          
* Create a .env file in the root directory of this project, and copy paste the contents of .env.sample into it.
* In .env, Replace:
  * VITE_SERVER_URI: With the path where freeapi server is running example http://localhost:8080 by default
  * VITE_PAYPAL_CLIENT_ID: With your own paypal client id.
* Run ```npm i ```
* Run ```npm run dev```, the development server will start on port 3000: Visit http://localhost:3000 to view the client app.

### Credits
 * FreeAPI Project:    https://github.com/hiteshchoudhary/apihub
 * API for countries & states: https://countriesnow.space/
 * Design Inspiration: https://www.figma.com/community/file/1219312065205187851

### Dependencies
* [React](https://github.com/facebook/react) : v18.2.0
* [Vite](https://vitejs.dev/) : v5.0.12
* [TailwindCSS](https://github.com/tailwindlabs/tailwindcss) : v3.3.6 
* State Management
    * [React Redux](https://github.com/reduxjs/react-redux) : v9.0.4
    * [Redux Toolkit](https://github.com/reduxjs/redux-toolkit) : v2.0.1
* API Calls
    * [Axios](https://github.com/axios/axios) : v1.6.2
* Payments
    * [React Paypal JS](https://github.com/paypal/react-paypal-js) : v8.1.3
    * [Paypal JS](https://github.com/paypal/paypal-js) : v8.0.0
* Date Picker
    * [React Day Picker](https://github.com/gpbl/react-day-picker) : v8.10.1
    * [Date fns](https://github.com/date-fns/date-fns) : v3.6.0
* Multilingual
    * [i18n](https://github.com/i18next/i18next) : v23.7.11
    * [react-i18next](https://github.com/i18next/react-i18next) : v6.20.1
* Form Handling
    * [React Hook Form](https://github.com/react-hook-form/react-hook-form) : v7.49.2
 



================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/index.html
================================================
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Ecommerce</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/package.json
================================================
{
  "name": "client_app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "devhost": "vite --host",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@paypal/react-paypal-js": "^8.1.3",
    "@reduxjs/toolkit": "^2.0.1",
    "axios": "^1.7.4",
    "date-fns": "^3.6.0",
    "i18next": "^23.7.11",
    "i18next-http-backend": "^2.4.2",
    "moment": "^2.29.4",
    "react": "^18.2.0",
    "react-day-picker": "^8.10.1",
    "react-dom": "^18.2.0",
    "react-hook-form": "^7.49.2",
    "react-i18next": "^13.5.0",
    "react-redux": "^9.0.4",
    "react-router-dom": "^6.20.1"
  },
  "devDependencies": {
    "@paypal/paypal-js": "^8.0.0",
    "@types/node": "^20.10.4",
    "@types/react": "^18.2.43",
    "@types/react-dom": "^18.2.17",
    "@typescript-eslint/eslint-plugin": "^6.14.0",
    "@typescript-eslint/parser": "^6.14.0",
    "@vitejs/plugin-react": "^4.2.1",
    "autoprefixer": "^10.4.16",
    "eslint": "^8.55.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.5",
    "postcss": "^8.4.32",
    "prettier": "3.2.5",
    "tailwindcss": "^3.3.6",
    "typescript": "^5.2.2",
    "vite": "^5.2.14"
  },
  "resolutions": {
    "cross-spawn": "^7.0.5",
    "nanoid": "^3.3.8"
  }
}


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/postcss.config.js
================================================
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/public/locales/ar/translation.json
================================================
{
  "en": "english",
  "ar": "عربي",
  "hn": "हिन्दी",
  "select": "يختار",
  "infoHeaderMessage": "",
  "companyName": "ecomm",
  "home": "بيت",
  "contact": "اتصال",
  "about": "عن",
  "login": "تسجيل الدخول",
  "searchProductsPlaceholder": "ما الذي تبحث عنه؟",
  "companyAddress": "عنوان طويل عشوائي يأتي هنا",
  "companyEmail": "email@email.com",
  "companyPhone": "+00 000 0000",
  "copyrightMessage": "حقوق الطبع والنشر 2024. جميع الحقوق محفوظة ©",
  "support": "يدعم",
  "days": "أيام",
  "hours": "ساعات",
  "minutes": "دقائق",
  "seconds": "دقائق",
  "bannerPromotion": "ارفع أسلوبك",
  "bannerPromotion2": "مع أحدث الوافدين لدينا",
  "categories": "فئات",
  "browseByCategory": "تصفح حسب الفئة",
  "pleaseTryAgainLater": "فشل التحميل، يرجى المحاولة مرة أخرى في وقت لاحق",
  "addToCart": "أضف إلى السلة",
  "ourProducts": "منتجاتنا",
  "exploreOurProducts": "استكشاف منتجاتنا",
  "viewAllProducts": "عرض جميع المنتجات",
  "thisMonth": "هذا الشهر",
  "bestSellingProducts": "أفضل المنتجات مبيعا",
  "viewAll": "عرض الكل",
  "freeAndFastDelivery": "تسليم مجاني وسريع",
  "freeDeliveryFor": "التوصيل مجاني لجميع الطلبات التي تزيد عن 200",
  "247customerService": "خدمة العملاء 24/7",
  "247customerServiceDescription": "دعم عملاء ودود على مدار 24 ساعة طوال أيام الأسبوع",
  "guranteeHeading": "ضمان استعادة الاموال",
  "guranteeDescription": "نقوم بإرجاع الأموال خلال 30 يومًا",
  "loadMore": "تحميل المزيد",
  "inStock": "في الأوراق المالية",
  "outOfStock": "إنتهى من المخزن",
  "removeFromCart": "إزالة من العربة",
  "relatedItems": "الأصناف المتعلقة",
  "enterYourDetailsBelow": "أدخل التفاصيل الخاصة بك أدناه",
  "email": "بريد إلكتروني",
  "password": "كلمة المرور",
  "forgotPassword": "نسيت كلمة المرور",
  "dontHaveAnAccountSignUp": "ليس لديك حساب؟ قم بالتسجيل",
  "emailIsRequired": "البريد الالكتروني مطلوب",
  "passwordIsRequired": "كلمة المرور مطلوبة",
  "invalidEmailAddress": "عنوان البريد الإلكتروني غير صالح",
  "myAccount": "حسابي",
  "manageAccount": "إدارة الحساب",
  "logout": "تسجيل خروج",
  "confirmation": "تأكيد",
  "yes": "نعم",
  "no": "لا",
  "areYouSureYouWantToLogout": "هل أنت متأكد أنك تريد تسجيل الخروج ؟",
  "ok": "نعم",
  "signup": "اشتراك",
  "username": "اسم المستخدم",
  "usernameIsRequired": "اسم المستخدم مطلوب",
  "confirmPassword": "تأكيد كلمة المرور",
  "passwordsDontMatch": "كلمات المرور غير متطابقة",
  "alreadyHaveAnAccountLogin": "لديك حساب الآن؟ تسجيل الدخول هنا",
  "signupSuccessful": "الاشتراك بنجاح",
  "proceedToLogin": "انتقل إلى تسجيل الدخول",
  "updateQuantity": "تحديث الكمية",
  "cartUpdatedSuccessfully": "تم تحديث سلة التسوق بنجاح",
  "maxQuantityReached": "تم الوصول إلى الحد الأقصى، لا يمكن إضافة المزيد من الوحدات",
  "subtotal": "المجموع الفرعي",
  "discount": "تخفيض",
  "total": "المجموع",
  "proceedToCheckout": "الشروع في الخروج",
  "summary": "ملخص",
  "selectCountry": "حدد الدولة",
  "selectState": "اختر ولايه",
  "selectCity": "اختر مدينة",
  "enterAddress1": "أدخل سطر العنوان 1",
  "enterAddress2": "أدخل سطر العنوان 2",
  "enterPincode": "أدخل الرمز السري",
  "addAddress": "اضف عنوان",
  "add": "يضيف",
  "cancel": "يلغي",
  "addressIsRequired": "العنوان مطلوب",
  "countryIsRequired": "الدولة مطلوبة",
  "stateIsRequired": "الدولة مطلوبة",
  "cityIsRequired": "المدينة مطلوبة",
  "pincodeIsRequired": "مطلوب الرمز السري",
  "invalidPincode": "الرمز السري غير صالح",
  "addressAddedSuccessfully": "تمت إضافة العنوان بنجاح",
  "addressUpdatedSuccessfully": "تم تحديث العنوان بنجاح",
  "selectAddress": "حدد العنوان",
  "use": "يستخدم",
  "code": "شفرة",
  "toGet": "تحصل",
  "off": "عن",
  "minimumPurchaseOf": "دقيقة شراء",
  "enterCouponCode": "أدخل رمز القسيمة",
  "applyCode": "تطبيق الكود",
  "removeCouponCode": "إزالة رمز القسيمة",
  "codeIsRequired": "الرمز مطلوب",
  "couponCodeAppliedSuccessfully": "تم تطبيق رمز القسيمة بنجاح",
  "couponCodeRemovedSuccessfully": "تمت إزالة رمز القسيمة بنجاح",
  "update": "تحديث",
  "updateAddress": "عنوان التحديث",
  "areYouSureYouWantToDeleteTheAddress": "هل أنت متأكد أنك تريد حذف العنوان",
  "deleteAddress": "حذف العنوان",
  "addressDeletedSuccessfully": "تم حذف العنوان بنجاح",
  "selectAddressToContinueToPayment": "حدد العنوان لمواصلة الدفع",
  "failedToProcessPaymentTryAgain": "فشلت في معالجة الدفع، يرجى المحاولة مرة أخرى في وقت لاحق",
  "paymentSuccessfullyCompleted": "اكتمل الدفع بنجاح",
  "goToHome": "اذهب إلى المنزل",
  "myOrders": "طلباتي",
  "editYourProfile": "عدل ملفك الشخصي",
  "firstName": "الاسم الأول",
  "lastName": "اسم العائلة",
  "countryCode": "الرقم الدولي",
  "phoneNumber": "رقم التليفون",
  "firstNameIsRequired": "الإسم الأول مطلوب",
  "lastNameIsRequired": "إسم العائلة مطلوب",
  "countryCodeIsRequired": "مطلوب رمز البلد",
  "phoneNumberIsRequired": "رقم الهاتف مطلوب",
  "invalidPhoneNumber": "رقم الهاتف غير صحيح",
  "invalidCountryCode": "رمز البلد غير صالح",
  "profileUpdatedSuccessfully": "تم تحديث الملف الشخصي بنجاح",
  "failedToFetchInformation": "فشل في جلب المعلومات، يرجى المحاولة مرة أخرى في وقت لاحق",
  "signInWithGoogle": "الدخول مع جوجل",
  "noOrdersFound": "لم يتم العثور على أية طلبات",
  "searchResults": "نتائج البحث",
  "noResultsFound": "لم يتم العثور على نتائج",
  "editProfile": "تعديل الملف الشخصي",
  "myAddresses": "عناويني",
  "accountSettings": "إعدادت الحساب",
  "changePassword": "تغيير كلمة المرور",
  "currentPassword": "كلمة السر الحالية",
  "newPassword": "كلمة المرور الجديدة",
  "confirmNewPassword": "تأكيد كلمة المرور الجديدة",
  "thisFieldIsRequired": "هذه الخانة مطلوبه",
  "passwordChangedSuccessfully": "تم تغيير الرقم السري بنجاح",
  "usernameMustBeThreeCharactersLong": "يجب أن يتكون اسم المستخدم من 3 أحرف على الأقل",
  "submit": "يُقدِّم",
  "passwordResetEmailSent": "تم إرسال بريد إعادة تعيين كلمة المرور على معرف البريد الخاص بك",
  "pageNotFound": "الصفحة غير موجودة",
  "resetPassword": "إعادة تعيين كلمة المرور",
  "reset": "إعادة ضبط",
  "tryAgainLater": "حاول مرة أخرى في وقت لاحق",
  "resetPasswordSuccessful": "تمت إعادة تعيين كلمة المرور بنجاح",
  "minPrice": "سعر دقيقة",
  "maxPrice": "الحد الأقصى للسعر",
  "to": "ل",
  "filter": "منقي",
  "invalidValue": "قيمة غير صالحة",
  "maxValueIsLessThanMinValue": "القيمة القصوى أقل من القيمة الدنيا",
  "addressDeleted": "تم حذف العنوان",
  "selectRange": "اختر نطاقا",
  "pending": "قيد الانتظار",
  "cancelled": "ألغيت",
  "delivered": "تم التوصيل",
  "pleaseSelectAOrderStatus": "يرجى تحديد حالة الطلب",
  "ourStory": "قصتنا"
}


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/public/locales/en/translation.json
================================================
{
  "en": "english",
  "ar": "عربي",
  "hn": "हिन्दी",
  "select": "Select",
  "infoHeaderMessage": "",
  "companyName": "ecomm",
  "home": "home",
  "contact": "contact",
  "about": "about",
  "login": "login",
  "searchProductsPlaceholder": "What are you looking for?",
  "companyAddress": "random long address comes here",
  "companyEmail": "email@email.com",
  "companyPhone": "+00 000 0000",
  "copyrightMessage": "© copyright right 2024. all right reserved",
  "support": "support",
  "days": "days",
  "hours": "hours",
  "minutes": "minutes",
  "seconds": "seconds",
  "bannerPromotion": "Elevate Your Style",
  "bannerPromotion2": "With Our Latest Arrivals",
  "categories": "categories",
  "browseByCategory": "browse by category",
  "pleaseTryAgainLater": "failed to load, please try again later",
  "addToCart": "add to cart",
  "ourProducts": "our products",
  "exploreOurProducts": "explore our products",
  "viewAllProducts": "view all products",
  "thisMonth": "this month",
  "bestSellingProducts": "best selling products",
  "viewAll": "view all",
  "freeAndFastDelivery": "free and fast delivery",
  "freeDeliveryFor": "free delivery for all orders over 200",
  "247customerService": "24/7 customer service",
  "247customerServiceDescription": "friendly 24/7 customer support",
  "guranteeHeading": "money back gurantee",
  "guranteeDescription": "we return money within 30 days",
  "loadMore": "load more",
  "inStock": "in stock",
  "outOfStock": "out of stock",
  "removeFromCart": "remove from cart",
  "relatedItems": "related items",
  "enterYourDetailsBelow": "enter your details below",
  "email": "email",
  "password": "password",
  "forgotPassword": "forgot password",
  "dontHaveAnAccountSignUp": "don't have an account ? signup",
  "emailIsRequired": "email is required",
  "passwordIsRequired": "password is required",
  "invalidEmailAddress": "invalid email address",
  "myAccount": "my account",
  "manageAccount": "manage account",
  "logout": "Logout",
  "confirmation": "confirmation",
  "yes": "yes",
  "no": "no",
  "areYouSureYouWantToLogout": "are you sure you want to logout ?",
  "ok": "ok",
  "signup": "signup",
  "username": "username",
  "usernameIsRequired": "username is required",
  "confirmPassword": "confirm password",
  "passwordsDontMatch": "passwords dont match",
  "alreadyHaveAnAccountLogin": "already have an account ?, login here",
  "signupSuccessful": "sign up successful",
  "proceedToLogin": "proceed to login",
  "updateQuantity": "update quantity",
  "cartUpdatedSuccessfully": "cart updated successfully",
  "maxQuantityReached": "max limit reached, cannot add any more units",
  "subtotal": "subtotal",
  "discount": "discount",
  "total": "total",
  "proceedToCheckout": "proceed to checkout",
  "summary": "summary",
  "selectCountry": "select country",
  "selectState": "select state",
  "selectCity": "select city",
  "enterAddress1": "enter address line 1",
  "enterAddress2": "enter address line 2",
  "enterPincode": "enter pincode",
  "addAddress": "add address",
  "add": "add",
  "cancel": "cancel",
  "addressIsRequired": "address is required",
  "countryIsRequired": "country is required",
  "stateIsRequired": "state is required",
  "cityIsRequired": "city is required",
  "pincodeIsRequired": "pincode is required",
  "invalidPincode": "invalid pincode",
  "addressAddedSuccessfully": "address added successfully",
  "addressUpdatedSuccessfully": "address updated successfully",
  "selectAddress": "select address",
  "use": "use",
  "code": "code",
  "toGet": "to get",
  "off": "off",
  "minimumPurchaseOf": "min purchase of",
  "enterCouponCode": "enter coupon code",
  "applyCode": "apply code",
  "removeCouponCode": "remove coupon code",
  "codeIsRequired": "code is required",
  "couponCodeAppliedSuccessfully": "coupon code applied successfully",
  "couponCodeRemovedSuccessfully": "coupon code removed successfully",
  "update": "update",
  "updateAddress": "update address",
  "areYouSureYouWantToDeleteTheAddress": "are you sure you want to delete the address",
  "deleteAddress": "delete address",
  "addressDeletedSuccessfully": "address deleted successfully",
  "selectAddressToContinueToPayment": "select address to continue to payment",
  "failedToProcessPaymentTryAgain": "failed to process payment, please try again later",
  "paymentSuccessfullyCompleted": "payment successfully completed",
  "goToHome": "go to home",
  "myOrders": "my orders",
  "editYourProfile": "edit your profile",
  "firstName": "first name",
  "lastName": "last name",
  "countryCode": "country code",
  "phoneNumber": "phone number",
  "firstNameIsRequired": "first name is required",
  "lastNameIsRequired": "last name is required",
  "countryCodeIsRequired": "country code is required",
  "phoneNumberIsRequired": "phone number is required",
  "invalidPhoneNumber": "invalid phone number",
  "invalidCountryCode": "invalid country code",
  "profileUpdatedSuccessfully": "profile updated successfully",
  "failedToFetchInformation": "failed to fetch information, please try again later",
  "signInWithGoogle": "sign in with google",
  "noOrdersFound": "no orders found",
  "searchResults": "search results",
  "noResultsFound": "no results found",
  "editProfile": "edit profile",
  "myAddresses": "my addresses",
  "accountSettings": "account settings",
  "changePassword": "change password",
  "currentPassword": "current password",
  "newPassword": "new password",
  "confirmNewPassword": "confirm new password",
  "thisFieldIsRequired": "this field is required",
  "passwordChangedSuccessfully": "password changed successfully",
  "usernameMustBeThreeCharactersLong": "username must be at least 3 characters long",
  "submit": "submit",
  "passwordResetEmailSent": "password reset mail has been sent on your mail id",
  "pageNotFound": "404: page not found",
  "resetPassword": "reset password",
  "reset": "reset",
  "tryAgainLater": "try again later",
  "resetPasswordSuccessful": "reset password successful",
  "minPrice": "min price",
  "maxPrice": "max price",
  "to": "to",
  "filter": "filter",
  "invalidValue": "invalid value",
  "maxValueIsLessThanMinValue": "max value is less than min value",
  "addressDeleted": "address deleted",
  "selectRange": "select range",
  "pending": "pending",
  "cancelled": "cancelled",
  "delivered": "delivered",
  "pleaseSelectAOrderStatus": "please select a order status",
  "ourStory": "our story"
}


================================================
FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/public/locales/hn/translation.json
================================================
{
  "en": "english",
  "ar": "عربي",
  "hn": "हिन्दी",
  "select": "चुनना",
  "infoHeaderMessage": "",
  "companyName": "ecomm",
  "home": "घर",
  "contact": "संपर्क",
  "about": "बारे में",
  "login": "लॉग इन",
  "searchProductsPlaceholder": "तुम क्या ढूंढ रहे हो?",
  "companyAddress": "पता",
  "companyEmail": "email@email.com",
  "companyPhone": "+00 0
Download .txt
gitextract_cp_asldb/

├── .babelrc
├── .commitlintrc.json
├── .dockerignore
├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.yaml
│       ├── code_coverage.yaml
│       ├── config.yml
│       ├── feature_request.yaml
│       └── frontend_contribution.yaml
├── .gitignore
├── .husky/
│   ├── commit-msg
│   └── pre-commit
├── .lintstagedrc
├── .prettierignore
├── .prettierrc
├── CONTRIBUTING.md
├── CONTRIBUTING_CODE_COVERAGE.md
├── CONTRIBUTING_FRONTEND.md
├── Dockerfile
├── LICENSE.md
├── README.md
├── docker-compose.prod.yml
├── docker-compose.yml
├── e2e/
│   ├── common.js
│   ├── db.js
│   ├── routes/
│   │   ├── apps/
│   │   │   └── todo.test.js
│   │   ├── healthcheck.test.js
│   │   └── seeds/
│   │       ├── chat-app.test.js
│   │       ├── ecommerce.test.js
│   │       ├── generated-credentials.test.js
│   │       ├── social-media.test.js
│   │       └── todo.test.js
│   └── test-server.js
├── examples/
│   ├── apps/
│   │   ├── auth/
│   │   │   └── .gitkeep
│   │   ├── chat-app/
│   │   │   └── web/
│   │   │       └── react-vite-tailwind/
│   │   │           ├── .eslintrc.cjs
│   │   │           ├── .gitignore
│   │   │           ├── README.md
│   │   │           ├── index.html
│   │   │           ├── package.json
│   │   │           ├── postcss.config.js
│   │   │           ├── src/
│   │   │           │   ├── App.tsx
│   │   │           │   ├── api/
│   │   │           │   │   └── index.ts
│   │   │           │   ├── components/
│   │   │           │   │   ├── Button.tsx
│   │   │           │   │   ├── Input.tsx
│   │   │           │   │   ├── Loader.tsx
│   │   │           │   │   ├── PrivateRoute.tsx
│   │   │           │   │   ├── PublicRoute.tsx
│   │   │           │   │   ├── Select.tsx
│   │   │           │   │   └── chat/
│   │   │           │   │       ├── AddChatModal.tsx
│   │   │           │   │       ├── ChatItem.tsx
│   │   │           │   │       ├── GroupChatDetailsModal.tsx
│   │   │           │   │       ├── MessageItem.tsx
│   │   │           │   │       └── Typing.tsx
│   │   │           │   ├── context/
│   │   │           │   │   ├── AuthContext.tsx
│   │   │           │   │   └── SocketContext.tsx
│   │   │           │   ├── index.css
│   │   │           │   ├── interfaces/
│   │   │           │   │   ├── api.ts
│   │   │           │   │   ├── chat.ts
│   │   │           │   │   └── user.ts
│   │   │           │   ├── main.tsx
│   │   │           │   ├── pages/
│   │   │           │   │   ├── chat.tsx
│   │   │           │   │   ├── login.tsx
│   │   │           │   │   └── register.tsx
│   │   │           │   ├── utils/
│   │   │           │   │   └── index.ts
│   │   │           │   └── vite-env.d.ts
│   │   │           ├── tailwind.config.js
│   │   │           ├── tsconfig.json
│   │   │           ├── tsconfig.node.json
│   │   │           └── vite.config.ts
│   │   ├── ecommerce/
│   │   │   ├── .gitkeep
│   │   │   └── web/
│   │   │       └── react-vite-redux-tailwind/
│   │   │           ├── .eslintrc.cjs
│   │   │           ├── .gitignore
│   │   │           ├── README.md
│   │   │           ├── index.html
│   │   │           ├── package.json
│   │   │           ├── postcss.config.js
│   │   │           ├── public/
│   │   │           │   └── locales/
│   │   │           │       ├── ar/
│   │   │           │       │   └── translation.json
│   │   │           │       ├── en/
│   │   │           │       │   └── translation.json
│   │   │           │       └── hn/
│   │   │           │           └── translation.json
│   │   │           ├── src/
│   │   │           │   ├── App.tsx
│   │   │           │   ├── RoutePaths.tsx
│   │   │           │   ├── components/
│   │   │           │   │   ├── basic/
│   │   │           │   │   │   ├── ArrowButton.tsx
│   │   │           │   │   │   ├── Button.tsx
│   │   │           │   │   │   ├── CarouselButtons.tsx
│   │   │           │   │   │   ├── Checkbox.tsx
│   │   │           │   │   │   ├── DateRangePicker.tsx
│   │   │           │   │   │   ├── Drawer.tsx
│   │   │           │   │   │   ├── Dropdown.tsx
│   │   │           │   │   │   ├── ErrorMessage.tsx
│   │   │           │   │   │   ├── FullPageLoadingSpinner.tsx
│   │   │           │   │   │   ├── Hamburger.tsx
│   │   │           │   │   │   ├── Image.tsx
│   │   │           │   │   │   ├── Input.tsx
│   │   │           │   │   │   ├── Link.tsx
│   │   │           │   │   │   ├── Modal.tsx
│   │   │           │   │   │   ├── NavItem.tsx
│   │   │           │   │   │   ├── NavList.tsx
│   │   │           │   │   │   ├── RadioButtons.tsx
│   │   │           │   │   │   ├── RoundedIcon.tsx
│   │   │           │   │   │   ├── SearchInput.tsx
│   │   │           │   │   │   ├── SelectionMenu.tsx
│   │   │           │   │   │   ├── TabItem.tsx
│   │   │           │   │   │   ├── Tabs.tsx
│   │   │           │   │   │   ├── Text.tsx
│   │   │           │   │   │   └── ToastMessage.tsx
│   │   │           │   │   ├── business/
│   │   │           │   │   │   ├── AddressCard.tsx
│   │   │           │   │   │   ├── AddressCardList.tsx
│   │   │           │   │   │   ├── CardContainer.tsx
│   │   │           │   │   │   ├── CartItem.tsx
│   │   │           │   │   │   ├── CartItemList.tsx
│   │   │           │   │   │   ├── CartSummary.tsx
│   │   │           │   │   │   ├── CategoryCard.tsx
│   │   │           │   │   │   ├── CompanyGurantee.tsx
│   │   │           │   │   │   ├── CouponCard.tsx
│   │   │           │   │   │   ├── CouponCardList.tsx
│   │   │           │   │   │   ├── FooterSection.tsx
│   │   │           │   │   │   ├── InvoiceAmountSummary.tsx
│   │   │           │   │   │   ├── OrderCard.tsx
│   │   │           │   │   │   ├── OrderItem.tsx
│   │   │           │   │   │   ├── OrderItemList.tsx
│   │   │           │   │   │   ├── OrderListFilters.tsx
│   │   │           │   │   │   ├── OrderSummary.tsx
│   │   │           │   │   │   ├── OrdersList.tsx
│   │   │           │   │   │   ├── Payment.tsx
│   │   │           │   │   │   ├── ProductCard.tsx
│   │   │           │   │   │   ├── ProductFilters.tsx
│   │   │           │   │   │   ├── ProductImagesView.tsx
│   │   │           │   │   │   ├── ProductList.tsx
│   │   │           │   │   │   ├── QuantityCounter.tsx
│   │   │           │   │   │   └── Timer.tsx
│   │   │           │   │   ├── icons/
│   │   │           │   │   │   ├── AccountIcon.tsx
│   │   │           │   │   │   ├── AddIcon.tsx
│   │   │           │   │   │   ├── CartIcon.tsx
│   │   │           │   │   │   ├── CloseIcon.tsx
│   │   │           │   │   │   ├── DeleteIcon.tsx
│   │   │           │   │   │   ├── DownArrow.tsx
│   │   │           │   │   │   ├── EditIcon.tsx
│   │   │           │   │   │   ├── ErrorIcon.tsx
│   │   │           │   │   │   ├── GeneralCategoryIcon.tsx
│   │   │           │   │   │   ├── GoogleIcon.tsx
│   │   │           │   │   │   ├── GuranteeIcon.tsx
│   │   │           │   │   │   ├── HamburgerIcon.tsx
│   │   │           │   │   │   ├── HeadphoneIcon.tsx
│   │   │           │   │   │   ├── HidePasswordIcon.tsx
│   │   │           │   │   │   ├── LeftArrow.tsx
│   │   │           │   │   │   ├── LoadingSpinner.tsx
│   │   │           │   │   │   ├── LogoutIcon.tsx
│   │   │           │   │   │   ├── OrderIcon.tsx
│   │   │           │   │   │   ├── RectangleIcon.tsx
│   │   │           │   │   │   ├── SearchIcon.tsx
│   │   │           │   │   │   ├── ShowPasswordIcon.tsx
│   │   │           │   │   │   ├── SubtractIcon.tsx
│   │   │           │   │   │   ├── TickIcon.tsx
│   │   │           │   │   │   ├── TruckIcon.tsx
│   │   │           │   │   │   └── UpArrow.tsx
│   │   │           │   │   ├── modals/
│   │   │           │   │   │   ├── addaddressmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── AddAddressModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── AddAddressModal.tsx
│   │   │           │   │   │   ├── changepasswordmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── ChangePasswordModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── ChangePasswordModal.tsx
│   │   │           │   │   │   ├── deleteaddressmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── DeleteAddressModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── DeleteAddressModal.tsx
│   │   │           │   │   │   ├── feedbackmodal/
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── FeedbackModal.tsx
│   │   │           │   │   │   ├── forgotpasswordmodal/
│   │   │           │   │   │   │   ├── container/
│   │   │           │   │   │   │   │   └── ForgotPasswordModalContainer.tsx
│   │   │           │   │   │   │   └── presentation/
│   │   │           │   │   │   │       └── ForgotPasswordModal.tsx
│   │   │           │   │   │   └── logoutmodal/
│   │   │           │   │   │       ├── container/
│   │   │           │   │   │       │   └── LogoutModalContainer.tsx
│   │   │           │   │   │       └── presentation/
│   │   │           │   │   │           └── LogoutModal.tsx
│   │   │           │   │   └── widgets/
│   │   │           │   │       ├── about/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── AboutContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── About.tsx
│   │   │           │   │       ├── allproductlist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── AllProductListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── AllProductList.tsx
│   │   │           │   │       ├── banner/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── BannerContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Banner.tsx
│   │   │           │   │       ├── cart/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CartContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Cart.tsx
│   │   │           │   │       ├── categorylist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CategoryListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── CategoryList.tsx
│   │   │           │   │       ├── checkout/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CheckoutContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Checkout.tsx
│   │   │           │   │       ├── companyguranteelist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── CompanyGuranteeListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── CompanyGuranteeList.tsx
│   │   │           │   │       ├── editaddresses/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── EditAddressesContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── EditAddresses.tsx
│   │   │           │   │       ├── editprofile/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── EditProfileContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── EditProfile.tsx
│   │   │           │   │       ├── exploreproductlist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── ExploreProductListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── ExploreProductList.tsx
│   │   │           │   │       ├── featuredproductlist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── FeaturedProductListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── FeaturedProductList.tsx
│   │   │           │   │       ├── footer/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── FooterContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Footer.tsx
│   │   │           │   │       ├── header/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── HeaderContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Header.tsx
│   │   │           │   │       ├── infoheader/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── InfoHeaderContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── InfoHeader.tsx
│   │   │           │   │       ├── login/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── LoginContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── Login.tsx
│   │   │           │   │       ├── myaccountoption/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── MyAccountOptionContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── MyAccountOption.tsx
│   │   │           │   │       ├── myorderslist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── MyOrdersListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── MyOrdersList.tsx
│   │   │           │   │       ├── orderdetail/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── OrderDetailContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── OrderDetail.tsx
│   │   │           │   │       ├── productdetails/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── ProductDetailsContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── ProductDetails.tsx
│   │   │           │   │       ├── relateditemslist/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── RelatedItemsListContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── RelatedItemsList.tsx
│   │   │           │   │       ├── resetforgottenpassword/
│   │   │           │   │       │   ├── container/
│   │   │           │   │       │   │   └── ResetForgottenPasswordContainer.tsx
│   │   │           │   │       │   └── presentation/
│   │   │           │   │       │       └── ResetForgottenPassword.tsx
│   │   │           │   │       └── signup/
│   │   │           │   │           ├── container/
│   │   │           │   │           │   └── SignupContainer.tsx
│   │   │           │   │           └── presentation/
│   │   │           │   │               └── Signup.tsx
│   │   │           │   ├── constants.ts
│   │   │           │   ├── data/
│   │   │           │   │   └── applicationData.tsx
│   │   │           │   ├── hooks/
│   │   │           │   │   ├── useBreakpointCheck.tsx
│   │   │           │   │   ├── useCustomNavigate.tsx
│   │   │           │   │   ├── useOnRefresh.tsx
│   │   │           │   │   └── useOutsideClick.tsx
│   │   │           │   ├── i18n.ts
│   │   │           │   ├── index.css
│   │   │           │   ├── layouts/
│   │   │           │   │   └── PageLayout.tsx
│   │   │           │   ├── main.tsx
│   │   │           │   ├── pages/
│   │   │           │   │   ├── about/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── AboutPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── AboutPage.tsx
│   │   │           │   │   ├── cart/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── CartPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── CartPage.tsx
│   │   │           │   │   ├── checkout/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── CheckoutPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── CheckoutPage.tsx
│   │   │           │   │   ├── home/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── HomePageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── HomePage.tsx
│   │   │           │   │   ├── login/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── LoginPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── LoginPage.tsx
│   │   │           │   │   ├── manageaccount/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ManageAccountPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ManageAccountPage.tsx
│   │   │           │   │   ├── orderdetail/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── OrderDetailPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── OrderDetailPage.tsx
│   │   │           │   │   ├── orders/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── OrdersPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── OrdersPage.tsx
│   │   │           │   │   ├── pagenotfound/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── PageNotFoundPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── PageNotFoundPage.tsx
│   │   │           │   │   ├── paymentfeedback/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── PaymentFeedbackPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── PaymentFeedbackPage.tsx
│   │   │           │   │   ├── productdetail/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ProductDetailPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ProductDetailPage.tsx
│   │   │           │   │   ├── products/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ProductsPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ProductsPage.tsx
│   │   │           │   │   ├── productsearch/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ProductSearchPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ProductSearchPage.tsx
│   │   │           │   │   ├── resetforgottenpassword/
│   │   │           │   │   │   ├── container/
│   │   │           │   │   │   │   └── ResetForgottenPasswordPageContainer.tsx
│   │   │           │   │   │   └── presentation/
│   │   │           │   │   │       └── ResetForgottenPasswordPage.tsx
│   │   │           │   │   └── signup/
│   │   │           │   │       ├── container/
│   │   │           │   │       │   └── SignupPageContainer.tsx
│   │   │           │   │       └── presentation/
│   │   │           │   │           └── SignupPage.tsx
│   │   │           │   ├── protectedroutes/
│   │   │           │   │   └── ForLoggedInUsers.tsx
│   │   │           │   ├── services/
│   │   │           │   │   ├── ApiError.ts
│   │   │           │   │   ├── ApiRequest.ts
│   │   │           │   │   ├── ApiResponse.ts
│   │   │           │   │   ├── CountryApiRequest.ts
│   │   │           │   │   ├── address/
│   │   │           │   │   │   ├── AddressService.ts
│   │   │           │   │   │   └── AddressTypes.ts
│   │   │           │   │   ├── auth/
│   │   │           │   │   │   ├── AuthService.ts
│   │   │           │   │   │   └── AuthTypes.ts
│   │   │           │   │   ├── cart/
│   │   │           │   │   │   ├── CartService.ts
│   │   │           │   │   │   └── CartTypes.ts
│   │   │           │   │   ├── category/
│   │   │           │   │   │   ├── CategoryService.ts
│   │   │           │   │   │   └── CategoryTypes.ts
│   │   │           │   │   ├── countryapi/
│   │   │           │   │   │   ├── CountryApiService.ts
│   │   │           │   │   │   └── CountryApiTypes.ts
│   │   │           │   │   ├── coupon/
│   │   │           │   │   │   ├── CouponService.ts
│   │   │           │   │   │   └── CouponTypes.ts
│   │   │           │   │   ├── order/
│   │   │           │   │   │   ├── OrderService.ts
│   │   │           │   │   │   └── OrderTypes.ts
│   │   │           │   │   ├── product/
│   │   │           │   │   │   ├── ProductService.ts
│   │   │           │   │   │   └── ProductTypes.ts
│   │   │           │   │   └── profile/
│   │   │           │   │       ├── ProfileService.ts
│   │   │           │   │       └── ProfileTypes.ts
│   │   │           │   ├── store/
│   │   │           │   │   ├── AuthSlice.ts
│   │   │           │   │   ├── BreakpointSlice.ts
│   │   │           │   │   ├── CartSlice.ts
│   │   │           │   │   ├── LanguageSlice.ts
│   │   │           │   │   ├── ToastMessageSlice.ts
│   │   │           │   │   └── index.ts
│   │   │           │   ├── styles/
│   │   │           │   │   └── DateRangePicker.css
│   │   │           │   ├── utils/
│   │   │           │   │   ├── asyncHandler.ts
│   │   │           │   │   ├── breakpointsHelper.ts
│   │   │           │   │   ├── commonHelper.ts
│   │   │           │   │   ├── countryApiAsyncHandler.ts
│   │   │           │   │   ├── dateTimeHelper.ts
│   │   │           │   │   └── languageHelpers.ts
│   │   │           │   └── vite-env.d.ts
│   │   │           ├── tailwind.config.js
│   │   │           ├── tsconfig.json
│   │   │           ├── tsconfig.node.json
│   │   │           └── vite.config.ts
│   │   ├── social-media/
│   │   │   └── .gitkeep
│   │   └── todo/
│   │       └── web/
│   │           └── react-vite-tailwind/
│   │               ├── .eslintrc.cjs
│   │               ├── .gitignore
│   │               ├── README.md
│   │               ├── index.html
│   │               ├── package.json
│   │               ├── postcss.config.js
│   │               ├── src/
│   │               │   ├── App.tsx
│   │               │   ├── api/
│   │               │   │   └── index.ts
│   │               │   ├── components/
│   │               │   │   ├── Button.tsx
│   │               │   │   ├── Header.tsx
│   │               │   │   ├── Input.tsx
│   │               │   │   ├── Loader.tsx
│   │               │   │   ├── ModalContainer.tsx
│   │               │   │   ├── Options.tsx
│   │               │   │   └── todos/
│   │               │   │       ├── CreateTodoModal.tsx
│   │               │   │       ├── DetailAndEditModal.tsx
│   │               │   │       ├── TabsHeader.tsx
│   │               │   │       └── TodoCard.tsx
│   │               │   ├── context/
│   │               │   │   └── TodoContext.tsx
│   │               │   ├── index.css
│   │               │   ├── interfaces/
│   │               │   │   ├── api.ts
│   │               │   │   └── todo.ts
│   │               │   ├── main.tsx
│   │               │   ├── utils/
│   │               │   │   └── index.ts
│   │               │   └── vite-env.d.ts
│   │               ├── tailwind.config.js
│   │               ├── tsconfig.json
│   │               ├── tsconfig.node.json
│   │               └── vite.config.ts
│   ├── kitchen-sink/
│   │   ├── cookies/
│   │   │   └── .gitkeep
│   │   ├── httpmethods/
│   │   │   └── .gitkeep
│   │   ├── images/
│   │   │   └── .gitkeep
│   │   ├── redirects/
│   │   │   └── .gitkeep
│   │   ├── requestinspections/
│   │   │   └── .gitkeep
│   │   ├── responseinspections/
│   │   │   └── .gitkeep
│   │   └── statuscodes/
│   │       └── web/
│   │           └── react-shadcn-tailwind-zustand/
│   │               ├── .eslintrc.cjs
│   │               ├── .gitignore
│   │               ├── README.md
│   │               ├── components.json
│   │               ├── index.html
│   │               ├── package.json
│   │               ├── postcss.config.js
│   │               ├── src/
│   │               │   ├── App.css
│   │               │   ├── App.tsx
│   │               │   ├── components/
│   │               │   │   └── ui/
│   │               │   │       ├── accordion.tsx
│   │               │   │       ├── button.tsx
│   │               │   │       ├── card.tsx
│   │               │   │       ├── command.tsx
│   │               │   │       ├── dialog.tsx
│   │               │   │       ├── label.tsx
│   │               │   │       ├── navigation-menu.tsx
│   │               │   │       ├── popover.tsx
│   │               │   │       ├── radio-group.tsx
│   │               │   │       └── select.tsx
│   │               │   ├── constants/
│   │               │   │   ├── index.ts
│   │               │   │   └── types.ts
│   │               │   ├── index.css
│   │               │   ├── layout/
│   │               │   │   ├── header/
│   │               │   │   │   ├── Header.tsx
│   │               │   │   │   ├── index.ts
│   │               │   │   │   └── menuItem.ts
│   │               │   │   ├── index.ts
│   │               │   │   └── pageContainer/
│   │               │   │       ├── PageContainer.tsx
│   │               │   │       └── index.ts
│   │               │   ├── lib/
│   │               │   │   └── utils.ts
│   │               │   ├── main.tsx
│   │               │   ├── pages/
│   │               │   │   ├── codesList/
│   │               │   │   │   ├── CodesList.tsx
│   │               │   │   │   ├── components/
│   │               │   │   │   │   ├── StatusAccordian.tsx
│   │               │   │   │   │   ├── index.ts
│   │               │   │   │   │   └── types.ts
│   │               │   │   │   └── index.ts
│   │               │   │   ├── findCode/
│   │               │   │   │   ├── FindCode.tsx
│   │               │   │   │   ├── components/
│   │               │   │   │   │   ├── ComboBox.tsx
│   │               │   │   │   │   └── index.ts
│   │               │   │   │   └── index.ts
│   │               │   │   ├── home/
│   │               │   │   │   ├── Home.tsx
│   │               │   │   │   ├── assets/
│   │               │   │   │   │   └── index.ts
│   │               │   │   │   ├── home.css
│   │               │   │   │   └── index.ts
│   │               │   │   ├── index.ts
│   │               │   │   └── quiz/
│   │               │   │       ├── Quiz.tsx
│   │               │   │       ├── components/
│   │               │   │       │   ├── QuestionsCard.tsx
│   │               │   │       │   └── index.ts
│   │               │   │       └── index.ts
│   │               │   ├── router/
│   │               │   │   ├── index.ts
│   │               │   │   ├── router.tsx
│   │               │   │   └── routes.ts
│   │               │   ├── services/
│   │               │   │   ├── codesList.ts
│   │               │   │   └── types.ts
│   │               │   ├── store/
│   │               │   │   └── store.ts
│   │               │   └── vite-env.d.ts
│   │               ├── tailwind.config.js
│   │               ├── tsconfig.json
│   │               ├── tsconfig.node.json
│   │               └── vite.config.ts
│   └── public/
│       ├── books/
│       │   └── .gitkeep
│       ├── cats/
│       │   └── .gitkeep
│       ├── dogs/
│       │   └── .gitkeep
│       ├── meals/
│       │   └── .gitkeep
│       ├── quotes/
│       │   └── .gitkeep
│       ├── randomjokes/
│       │   └── .gitkeep
│       ├── randomproducts/
│       │   └── .gitkeep
│       ├── randomusers/
│       │   └── .gitkeep
│       ├── stocks/
│       │   └── .gitkeep
│       └── youtube/
│           └── .gitkeep
├── nodemon.json
├── package.json
├── playwright.config.js
├── prepare.js
├── public/
│   ├── assets/
│   │   └── templates/
│   │       ├── html_response.html
│   │       └── xml_response.xml
│   ├── images/
│   │   └── .gitkeep
│   └── temp/
│       └── .gitkeep
└── src/
    ├── app.js
    ├── constants.js
    ├── controllers/
    │   ├── apps/
    │   │   ├── auth/
    │   │   │   └── user.controllers.js
    │   │   ├── chat-app/
    │   │   │   ├── chat.controllers.js
    │   │   │   └── message.controllers.js
    │   │   ├── ecommerce/
    │   │   │   ├── address.controllers.js
    │   │   │   ├── cart.controllers.js
    │   │   │   ├── category.controllers.js
    │   │   │   ├── coupon.controllers.js
    │   │   │   ├── order.controllers.js
    │   │   │   ├── product.controllers.js
    │   │   │   └── profile.controllers.js
    │   │   ├── social-media/
    │   │   │   ├── bookmark.controllers.js
    │   │   │   ├── comment.controllers.js
    │   │   │   ├── follow.controllers.js
    │   │   │   ├── like.controllers.js
    │   │   │   ├── post.controllers.js
    │   │   │   └── profile.controllers.js
    │   │   └── todo/
    │   │       └── todo.controllers.js
    │   ├── healthcheck.controllers.js
    │   ├── kitchen-sink/
    │   │   ├── cookie.controllers.js
    │   │   ├── httpmethod.controllers.js
    │   │   ├── image.controllers.js
    │   │   ├── redirect.controllers.js
    │   │   ├── requestinspection.controllers.js
    │   │   ├── responseinspection.controllers.js
    │   │   └── statuscode.controllers.js
    │   └── public/
    │       ├── book.controllers.js
    │       ├── cat.controllers.js
    │       ├── dog.controllers.js
    │       ├── meal.controllers.js
    │       ├── quote.controllers.js
    │       ├── randomjoke.controllers.js
    │       ├── randomproduct.controllers.js
    │       ├── randomuser.controllers.js
    │       ├── stock.controllers.js
    │       └── youtube.controllers.js
    ├── db/
    │   └── index.js
    ├── index.js
    ├── json/
    │   ├── books.json
    │   ├── cats.json
    │   ├── dogs.json
    │   ├── meals.json
    │   ├── nse-stocks.json
    │   ├── quotes.json
    │   ├── randomjoke.json
    │   ├── randomproduct.json
    │   ├── randomuser.json
    │   ├── status-codes.json
    │   └── youtube/
    │       ├── channel.json
    │       ├── comments.json
    │       ├── playlistitems.json
    │       ├── playlists.json
    │       └── videos.json
    ├── logger/
    │   ├── morgan.logger.js
    │   └── winston.logger.js
    ├── middlewares/
    │   ├── auth.middlewares.js
    │   ├── error.middlewares.js
    │   └── multer.middlewares.js
    ├── models/
    │   └── apps/
    │       ├── auth/
    │       │   └── user.models.js
    │       ├── chat-app/
    │       │   ├── chat.models.js
    │       │   └── message.models.js
    │       ├── ecommerce/
    │       │   ├── address.models.js
    │       │   ├── cart.models.js
    │       │   ├── category.models.js
    │       │   ├── coupon.models.js
    │       │   ├── order.models.js
    │       │   ├── product.models.js
    │       │   └── profile.models.js
    │       ├── social-media/
    │       │   ├── bookmark.models.js
    │       │   ├── comment.models.js
    │       │   ├── follow.models.js
    │       │   ├── like.models.js
    │       │   ├── post.models.js
    │       │   └── profile.models.js
    │       └── todo/
    │           └── todo.models.js
    ├── passport/
    │   └── index.js
    ├── routes/
    │   ├── apps/
    │   │   ├── auth/
    │   │   │   └── user.routes.js
    │   │   ├── chat-app/
    │   │   │   ├── chat.routes.js
    │   │   │   └── message.routes.js
    │   │   ├── ecommerce/
    │   │   │   ├── address.routes.js
    │   │   │   ├── cart.routes.js
    │   │   │   ├── category.routes.js
    │   │   │   ├── coupon.routes.js
    │   │   │   ├── order.routes.js
    │   │   │   ├── product.routes.js
    │   │   │   └── profile.routes.js
    │   │   ├── social-media/
    │   │   │   ├── bookmark.routes.js
    │   │   │   ├── comment.routes.js
    │   │   │   ├── follow.routes.js
    │   │   │   ├── like.routes.js
    │   │   │   ├── post.routes.js
    │   │   │   └── profile.routes.js
    │   │   └── todo/
    │   │       └── todo.routes.js
    │   ├── healthcheck.routes.js
    │   ├── kitchen-sink/
    │   │   ├── cookie.routes.js
    │   │   ├── httpmethod.routes.js
    │   │   ├── image.routes.js
    │   │   ├── redirect.routes.js
    │   │   ├── requestinspection.routes.js
    │   │   ├── responseinspection.routes.js
    │   │   └── statuscode.routes.js
    │   └── public/
    │       ├── book.routes.js
    │       ├── cat.routes.js
    │       ├── dog.routes.js
    │       ├── meal.routes.js
    │       ├── quote.routes.js
    │       ├── randomjoke.routes.js
    │       ├── randomproduct.routes.js
    │       ├── randomuser.routes.js
    │       ├── stock.routes.js
    │       └── youtube.routes.js
    ├── seeds/
    │   ├── _constants.js
    │   ├── chat-app.seeds.js
    │   ├── ecommerce.seeds.js
    │   ├── social-media.seeds.js
    │   ├── todo.seeds.js
    │   └── user.seeds.js
    ├── socket/
    │   └── index.js
    ├── swagger.yaml
    ├── utils/
    │   ├── ApiError.js
    │   ├── ApiResponse.js
    │   ├── asyncHandler.js
    │   ├── helpers.js
    │   └── mail.js
    └── validators/
        ├── apps/
        │   ├── auth/
        │   │   └── user.validators.js
        │   ├── chat-app/
        │   │   ├── chat.validators.js
        │   │   └── message.validators.js
        │   ├── ecommerce/
        │   │   ├── address.validators.js
        │   │   ├── cart.validators.js
        │   │   ├── category.validators.js
        │   │   ├── coupon.validators.js
        │   │   ├── order.validators.js
        │   │   ├── product.validators.js
        │   │   └── profile.validators.js
        │   ├── social-media/
        │   │   ├── comment.validators.js
        │   │   ├── post.validators.js
        │   │   └── profile.validators.js
        │   └── todo/
        │       └── todo.validators.js
        ├── common/
        │   └── mongodb.validators.js
        ├── kitchen-sink/
        │   ├── cookie.validators.js
        │   ├── redirect.validators.js
        │   ├── responseinspection.validators.js
        │   └── statuscode.validators.js
        └── validate.js
Download .txt
SYMBOL INDEX (371 symbols across 156 files)

FILE: e2e/common.js
  constant URL (line 7) | const URL = `http://localhost:${process.env.PORT || 8080}`;

FILE: e2e/db.js
  constant MONGO_MEMORY_SERVER_PORT (line 4) | const MONGO_MEMORY_SERVER_PORT = process.env.MONGO_MEMORY_SERVER_PORT ||...
  constant MONGODB_URL (line 5) | const MONGODB_URL = `mongodb://127.0.0.1:${MONGO_MEMORY_SERVER_PORT}/`;

FILE: e2e/test-server.js
  constant PORT (line 8) | const PORT = process.env.PORT || 8080;

FILE: examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/api.ts
  type FreeAPISuccessResponseInterface (line 1) | interface FreeAPISuccessResponseInterface {

FILE: examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/chat.ts
  type ChatListItemInterface (line 3) | interface ChatListItemInterface {
  type ChatMessageInterface (line 14) | interface ChatMessageInterface {

FILE: examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/user.ts
  type UserInterface (line 1) | interface UserInterface {

FILE: examples/apps/chat-app/web/react-vite-tailwind/src/pages/chat.tsx
  constant CONNECTED_EVENT (line 31) | const CONNECTED_EVENT = "connected";
  constant DISCONNECT_EVENT (line 32) | const DISCONNECT_EVENT = "disconnect";
  constant JOIN_CHAT_EVENT (line 33) | const JOIN_CHAT_EVENT = "joinChat";
  constant NEW_CHAT_EVENT (line 34) | const NEW_CHAT_EVENT = "newChat";
  constant TYPING_EVENT (line 35) | const TYPING_EVENT = "typing";
  constant STOP_TYPING_EVENT (line 36) | const STOP_TYPING_EVENT = "stopTyping";
  constant MESSAGE_RECEIVED_EVENT (line 37) | const MESSAGE_RECEIVED_EVENT = "messageReceived";
  constant LEAVE_CHAT_EVENT (line 38) | const LEAVE_CHAT_EVENT = "leaveChat";
  constant UPDATE_GROUP_NAME_EVENT (line 39) | const UPDATE_GROUP_NAME_EVENT = "updateGroupName";
  constant MESSAGE_DELETE_EVENT (line 40) | const MESSAGE_DELETE_EVENT = "messageDeleted";

FILE: examples/apps/chat-app/web/react-vite-tailwind/src/utils/index.ts
  class LocalStorage (line 91) | class LocalStorage {
    method get (line 93) | static get(key: string) {
    method set (line 107) | static set(key: string, value: any) {
    method remove (line 113) | static remove(key: string) {
    method clear (line 119) | static clear() {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/App.tsx
  function App (line 3) | function App() {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/ArrowButton.tsx
  type ArrowButtonProps (line 6) | interface ArrowButtonProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Button.tsx
  type ButtonProps (line 5) | interface ButtonProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/CarouselButtons.tsx
  type CarouselButtons (line 6) | interface CarouselButtons {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Checkbox.tsx
  type CheckboxActionsRef (line 6) | interface CheckboxActionsRef<T> {
  type CheckboxProps (line 9) | interface CheckboxProps<T> {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/DateRangePicker.tsx
  type DateRangePickerActionsRef (line 12) | interface DateRangePickerActionsRef {
  type DateRangePickerProps (line 15) | interface DateRangePickerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Drawer.tsx
  type DrawerProps (line 7) | interface DrawerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Dropdown.tsx
  type DropdownActions (line 18) | interface DropdownActions {
  type DropdownProps (line 22) | interface DropdownProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/ErrorMessage.tsx
  type ErrorMessageProps (line 5) | interface ErrorMessageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Hamburger.tsx
  type HamburgerProps (line 8) | interface HamburgerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Image.tsx
  type ImageProps (line 3) | interface ImageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Input.tsx
  type InputProps (line 7) | interface InputProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Link.tsx
  type LinkProps (line 5) | interface LinkProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Modal.tsx
  type ModalProps (line 5) | interface ModalProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/NavItem.tsx
  type NavItemProps (line 6) | interface NavItemProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/NavList.tsx
  type NavListProps (line 5) | interface NavListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/RadioButtons.tsx
  type RadioButtonsProps (line 6) | interface RadioButtonsProps<T> {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/RoundedIcon.tsx
  type RoundedIconProps (line 1) | interface RoundedIconProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/SearchInput.tsx
  type SearchInputProps (line 5) | interface SearchInputProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/SelectionMenu.tsx
  type SelectionMenuProps (line 9) | interface SelectionMenuProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/TabItem.tsx
  type TabItemProps (line 5) | interface TabItemProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Tabs.tsx
  type TabsProps (line 6) | interface TabsProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Text.tsx
  type TextProps (line 3) | interface TextProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/ToastMessage.tsx
  type ToastMessageProps (line 7) | interface ToastMessageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/AddressCard.tsx
  type AddressCardProps (line 11) | interface AddressCardProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/AddressCardList.tsx
  type AddressCardListProps (line 4) | interface AddressCardListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CardContainer.tsx
  type CardContainerProps (line 8) | interface CardContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CartItem.tsx
  type CartItemProps (line 15) | interface CartItemProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CartItemList.tsx
  type CartItemListProps (line 5) | interface CartItemListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CartSummary.tsx
  type CartSummaryProps (line 9) | interface CartSummaryProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CategoryCard.tsx
  type CategoryProps (line 6) | interface CategoryProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CouponCard.tsx
  type CouponCardProps (line 4) | interface CouponCardProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CouponCardList.tsx
  type CouponCardListProps (line 5) | interface CouponCardListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/FooterSection.tsx
  type FooterSectionProps (line 4) | interface FooterSectionProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/InvoiceAmountSummary.tsx
  type InvoiceAmountSummaryProps (line 5) | interface InvoiceAmountSummaryProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderCard.tsx
  type OrderCardProps (line 11) | interface OrderCardProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderItem.tsx
  type OrderItemProps (line 10) | interface OrderItemProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderItemList.tsx
  type OrderItemListProps (line 4) | interface OrderItemListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderListFilters.tsx
  type OrderListFiltersProps (line 13) | interface OrderListFiltersProps {
  method forceSetCheckedItems (line 31) | forceSetCheckedItems(_) {}
  method forceSetSelectedRange (line 34) | forceSetSelectedRange(_) {}

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderSummary.tsx
  type OrderSummaryProps (line 7) | interface OrderSummaryProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrdersList.tsx
  type OrdersListProps (line 7) | interface OrdersListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/Payment.tsx
  type PaymentProps (line 10) | interface PaymentProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductCard.tsx
  type ProductCardProps (line 10) | interface ProductCardProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductFilters.tsx
  type ProductFiltersProps (line 9) | interface ProductFiltersProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductImagesView.tsx
  type ProductImagesViewProps (line 6) | interface ProductImagesViewProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductList.tsx
  type ProductListProps (line 5) | interface ProductListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/QuantityCounter.tsx
  type QuantityCounterProps (line 6) | interface QuantityCounterProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/Timer.tsx
  type TimerProps (line 9) | interface TimerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/addaddressmodal/container/AddAddressModalContainer.tsx
  type DropdownListActions (line 16) | interface DropdownListActions  {
  type DropdownListState (line 28) | interface DropdownListState  {
  type AddAddressModalContainerProps (line 39) | interface AddAddressModalContainerProps {
  function dropdownListsReducer (line 45) | function dropdownListsReducer(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/addaddressmodal/presentation/AddAddressModal.tsx
  type AddAddressModalProps (line 20) | interface AddAddressModalProps {
  method forceSetSelectedItem (line 73) | forceSetSelectedItem(_) {}
  method forceSetSelectedItem (line 74) | forceSetSelectedItem(_) {}
  method forceSetSelectedItem (line 75) | forceSetSelectedItem(_) {}

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/changepasswordmodal/container/ChangePasswordModalContainer.tsx
  type ChangePasswordModalContainerProps (line 9) | interface ChangePasswordModalContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/changepasswordmodal/presentation/ChangePasswordModal.tsx
  type ChangePasswordModalProps (line 9) | interface ChangePasswordModalProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/deleteaddressmodal/container/DeleteAddressModalContainer.tsx
  type DeleteAddressModalContainerProps (line 9) | interface DeleteAddressModalContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/deleteaddressmodal/presentation/DeleteAddressModal.tsx
  type DeleteAddressModalProps (line 5) | interface DeleteAddressModalProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/feedbackmodal/presentation/FeedbackModal.tsx
  type FeedbackModalProps (line 7) | interface FeedbackModalProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/forgotpasswordmodal/container/ForgotPasswordModalContainer.tsx
  type ForgotPasswordModalContainerProps (line 9) | interface ForgotPasswordModalContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/forgotpasswordmodal/presentation/ForgotPasswordModal.tsx
  type ForgotPasswordProps (line 14) | interface ForgotPasswordProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/logoutmodal/container/LogoutModalContainer.tsx
  type LogoutModalContainerProps (line 9) | interface LogoutModalContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/logoutmodal/presentation/LogoutModal.tsx
  type LogoutModalProps (line 5) | interface LogoutModalProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/allproductlist/container/AllProductListContainer.tsx
  type AllProductListContainerProps (line 8) | interface AllProductListContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/allproductlist/presentation/AllProductList.tsx
  type AllProductListProps (line 13) | interface AllProductListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/banner/presentation/Banner.tsx
  type BannerProps (line 7) | interface BannerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/cart/presentation/Cart.tsx
  type CartProps (line 7) | interface CartProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/categorylist/presentation/CategoryList.tsx
  type CategoryList (line 10) | interface CategoryList {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/checkout/presentation/Checkout.tsx
  type CheckoutProps (line 27) | interface CheckoutProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/companyguranteelist/presentation/CompanyGuranteeList.tsx
  type CompanyGuranteeListProps (line 5) | interface CompanyGuranteeListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/editaddresses/presentation/EditAddresses.tsx
  type EditAddressesProps (line 8) | interface EditAddressesProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/editprofile/presentation/EditProfile.tsx
  type EditProfileProps (line 16) | interface EditProfileProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/exploreproductlist/presentation/ExploreProductList.tsx
  type ExploreProductListProps (line 8) | interface ExploreProductListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/featuredproductlist/presentation/FeaturedProductList.tsx
  type FeaturedProductListProps (line 8) | interface FeaturedProductListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/header/presentation/Header.tsx
  type HeaderProps (line 13) | interface HeaderProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/infoheader/presentation/InfoHeader.tsx
  type InfoHeaderProps (line 11) | interface InfoHeaderProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/login/presentation/Login.tsx
  type LoginProps (line 17) | interface LoginProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/myaccountoption/presentation/MyAccountOption.tsx
  type MyAccountOptionProps (line 6) | interface MyAccountOptionProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/myorderslist/presentation/MyOrdersList.tsx
  type MyOrdersListProps (line 8) | interface MyOrdersListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/orderdetail/container/OrderDetailContainer.tsx
  type OrderDetailContainerProps (line 7) | interface OrderDetailContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/orderdetail/presentation/OrderDetail.tsx
  type OrderDetailProps (line 8) | interface OrderDetailProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/productdetails/container/ProductDetailsContainer.tsx
  type ProductDetailsContainerProps (line 15) | interface ProductDetailsContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/productdetails/presentation/ProductDetails.tsx
  type ProductDetailsProps (line 13) | interface ProductDetailsProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/relateditemslist/container/RelatedItemsListContainer.tsx
  type RelatedItemsListContainerProps (line 8) | interface RelatedItemsListContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/relateditemslist/presentation/RelatedItemsList.tsx
  type RelatedItemsListProps (line 7) | interface RelatedItemsListProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/resetforgottenpassword/container/ResetForgottenPasswordContainer.tsx
  type ResetForgottenPasswordContainerProps (line 9) | interface ResetForgottenPasswordContainerProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/resetforgottenpassword/presentation/ResetForgottenPassword.tsx
  type ResetForgottenPasswordProps (line 13) | interface ResetForgottenPasswordProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/signup/presentation/Signup.tsx
  type SignupProps (line 17) | interface SignupProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/constants.ts
  type DropdownTypes (line 6) | enum DropdownTypes {
  type DropdownItem (line 11) | interface DropdownItem {
  type SelectionMenuItem (line 19) | interface SelectionMenuItem {
  type SUPPORTED_LANGUAGES (line 26) | enum SUPPORTED_LANGUAGES {
  constant DEFAULT_LANGUAGE (line 32) | const DEFAULT_LANGUAGE = SUPPORTED_LANGUAGES.english;
  type LOCAL_STORAGE_KEYS (line 35) | enum LOCAL_STORAGE_KEYS {
  type BREAKPOINTS (line 42) | enum BREAKPOINTS {
  type NavigationOption (line 51) | interface NavigationOption {
  type DrawerOption (line 60) | interface DrawerOption  {
  type ButtonTypes (line 67) | enum ButtonTypes {
  type LinkTypes (line 74) | enum LinkTypes {
  type DATE_TIME_FORMATS (line 80) | enum DATE_TIME_FORMATS {
  type DURATION (line 86) | interface DURATION {
  type CategoryIcon (line 94) | interface CategoryIcon  { [id: string]: React.ReactElement }
  type CARD_CONTAINER_OPTION (line 97) | enum CARD_CONTAINER_OPTION {
  type COMPANY_GURANTEE (line 104) | interface COMPANY_GURANTEE {
  type ARROW_BUTTONS (line 112) | enum ARROW_BUTTONS {
  type QUERY_PARAMS (line 119) | enum QUERY_PARAMS {
  type ROUTE_PATHS (line 128) | enum ROUTE_PATHS {
  type PUBLIC_IMAGE_PATHS (line 147) | enum PUBLIC_IMAGE_PATHS {
  constant REGEX_PATTERNS (line 155) | const REGEX_PATTERNS = {
  constant MIN_USERNAME_LENGTH (line 162) | const MIN_USERNAME_LENGTH = 3;
  type LoginFormFields (line 165) | interface LoginFormFields {
  type SignupFormFields (line 171) | interface SignupFormFields {
  type TOAST_MESSAGE_TYPES (line 179) | enum TOAST_MESSAGE_TYPES {
  type ADDRESS_FORM_KEYS (line 185) | enum ADDRESS_FORM_KEYS  {
  type AddressFormFields (line 194) | interface AddressFormFields {
  type CheckoutFormFields (line 203) | interface CheckoutFormFields {
  type ProfileFormFields (line 207) | interface ProfileFormFields {
  type CheckoutApplyCouponCodeFields (line 214) | interface CheckoutApplyCouponCodeFields {
  type RADIO_BUTTON_TYPE (line 218) | interface RADIO_BUTTON_TYPE<T> {
  type CHECKBOX_TYPE (line 226) | interface CHECKBOX_TYPE<T> {
  type TabItemConfig (line 238) | interface TabItemConfig {
  type ChangePasswordFields (line 244) | interface ChangePasswordFields {
  type ForgotPasswordFields (line 251) | interface ForgotPasswordFields {
  type ResetForgottenPasswordFields (line 256) | interface ResetForgottenPasswordFields {
  type ProductFilterFields (line 262) | interface ProductFilterFields {
  type OrderListFilterFields (line 269) | interface OrderListFilterFields {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/data/applicationData.tsx
  constant DRAWER_ITEMS (line 19) | const DRAWER_ITEMS: Array<NavigationOption> = [
  constant MY_ACCOUNT_OPTIONS (line 52) | const MY_ACCOUNT_OPTIONS: Array<SelectionMenuItem> = [
  constant BANNER_PROMOTION_END_DATE (line 70) | const BANNER_PROMOTION_END_DATE = "2023-04-30T00:00:00";
  constant CATEGORY_ICONS (line 72) | const CATEGORY_ICONS: CategoryIcon = {};
  constant DEFAULT_CURRENCY (line 74) | const DEFAULT_CURRENCY = "INR";
  constant DEFAULT_COUNTRY (line 76) | const DEFAULT_COUNTRY = "United Arab Emirates";
  constant COUNTRIES_DROPDOWN_LIST (line 78) | const COUNTRIES_DROPDOWN_LIST: DropdownItem[] = [{id: 1, text: DEFAULT_C...
  constant COMPANY_GURANTEE_LIST (line 79) | const COMPANY_GURANTEE_LIST: COMPANY_GURANTEE[] = [
  constant EXPLORE_PRODUCTS_COUNT (line 100) | const EXPLORE_PRODUCTS_COUNT = 8;
  constant FEATURED_PRODUCTS_COUNT (line 101) | const FEATURED_PRODUCTS_COUNT = 4;
  constant RELATED_PRODUCTS_COUNT (line 102) | const RELATED_PRODUCTS_COUNT = 4;
  type PAYMENT_TYPES (line 104) | enum PAYMENT_TYPES {
  constant MANAGE_ACCOUNT_TABS (line 108) | const MANAGE_ACCOUNT_TABS: Array<TabItemConfig> = [
  type ORDER_STATUS (line 119) | enum ORDER_STATUS {
  constant ORDER_STATUS_FILTERS_CHECKBOX (line 124) | const ORDER_STATUS_FILTERS_CHECKBOX: Array<CHECKBOX_TYPE<null>> = [

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/pages/orderdetail/presentation/OrderDetailPage.tsx
  type OrderDetailPageProps (line 4) | interface OrderDetailPageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/pages/paymentfeedback/presentation/PaymentFeedbackPage.tsx
  type PaymentFeedbackPageProps (line 7) | interface PaymentFeedbackPageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/pages/productdetail/presentation/ProductDetailPage.tsx
  type ProductDetailPageProps (line 4) | interface ProductDetailPageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/pages/products/presentation/ProductsPage.tsx
  type ProductsPageProps (line 3) | interface ProductsPageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/pages/productsearch/presentation/ProductSearchPage.tsx
  type ProductSearchPageProps (line 4) | interface ProductSearchPageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/pages/resetforgottenpassword/presentation/ResetForgottenPasswordPage.tsx
  type ResetForgottenPasswordPageProps (line 8) | interface ResetForgottenPasswordPageProps {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/ApiError.ts
  class ApiErrorResponse (line 3) | class ApiErrorResponse {
    method constructor (line 4) | constructor(
  class ApiError (line 11) | class ApiError {
    method constructor (line 13) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/ApiRequest.ts
  class ApiRequest (line 6) | class ApiRequest {
    method constructor (line 7) | constructor(public url: string) {}
    method getRequest (line 9) | async getRequest<T>(
    method postRequest (line 22) | async postRequest<T>(
    method putRequest (line 32) | async putRequest<T>(
    method deleteRequest (line 42) | async deleteRequest<T>(
    method patchRequest (line 51) | async patchRequest<T>(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/ApiResponse.ts
  class ApiResponse (line 1) | class ApiResponse<T> {
    method constructor (line 2) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/CountryApiRequest.ts
  class CountryApiRequest (line 8) | class CountryApiRequest {
    method constructor (line 9) | constructor(public url: string) {}
    method getRequest (line 11) | async getRequest<T>(
    method postRequest (line 24) | async postRequest<T>(
    method putRequest (line 36) | async putRequest<T>(
    method deleteRequest (line 48) | async deleteRequest<T>(
    method patchRequest (line 59) | async patchRequest<T>(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/address/AddressService.ts
  class AddressService (line 6) | class AddressService {
    method createAddress (line 10) | async createAddress(
    method updateAddress (line 38) | async updateAddress(
    method deleteAddress (line 66) | async deleteAddress(addressId: string): Promise<boolean | ApiError> {
    method getAllAddressesAsync (line 80) | async getAllAddressesAsync(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/address/AddressTypes.ts
  class AddressClass (line 1) | class AddressClass {
    method constructor (line 2) | constructor(
  class AddressListClass (line 17) | class AddressListClass {
    method constructor (line 18) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/auth/AuthService.ts
  class AuthService (line 11) | class AuthService {
    method loginService (line 16) | async loginService(
    method getCurrentUser (line 41) | async getCurrentUser(): Promise<User | ApiError> {
    method logoutService (line 55) | async logoutService(): Promise<boolean | ApiError> {
    method signUp (line 69) | async signUp(
    method changePassword (line 93) | async changePassword(
    method forgotPassword (line 112) | async forgotPassword(
    method resetForgottenPassword (line 130) | async resetForgottenPassword(
    method refreshAccessToken (line 150) | async refreshAccessToken(): Promise<

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/auth/AuthTypes.ts
  type LOGIN_TYPES (line 4) | enum LOGIN_TYPES {
  type USER_ROLES (line 11) | enum USER_ROLES {
  class LoginResp (line 16) | class LoginResp {
    method constructor (line 17) | constructor(
  class RefreshTokenResp (line 24) | class RefreshTokenResp {
    method constructor (line 25) | constructor(
  class User (line 33) | class User {
    method constructor (line 34) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/cart/CartService.ts
  class CartService (line 6) | class CartService {
    method getUserCart (line 9) | async getUserCart(): Promise<UserCart | ApiError> {
    method addOrUpdateItemInCart (line 23) | async addOrUpdateItemInCart(
    method removeItemFromCart (line 39) | async removeItemFromCart(productId: string): Promise<UserCart | ApiErr...

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/cart/CartTypes.ts
  class CartItemClass (line 4) | class CartItemClass {
    method constructor (line 5) | constructor(
  class UserCart (line 13) | class UserCart {
    method constructor (line 14) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/category/CategoryService.ts
  class CategoryService (line 6) | class CategoryService {
    method getAllCategoriesAsync (line 12) | async getAllCategoriesAsync(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/category/CategoryTypes.ts
  class Category (line 1) | class Category {
    method constructor (line 2) | constructor(
  class Categories (line 12) | class Categories {
    method constructor (line 13) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/countryapi/CountryApiService.ts
  class CountryApiService (line 6) | class CountryApiService {
    method getStatesOfACountry (line 12) | async getStatesOfACountry(
    method getCitiesOfAState (line 32) | async getCitiesOfAState(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/countryapi/CountryApiTypes.ts
  class CountryApiErrorResponse (line 1) | class CountryApiErrorResponse {
    method constructor (line 2) | constructor(public error: boolean, public msg: string) {}
  class CountryApiResponse (line 4) | class CountryApiResponse<T> {
    method constructor (line 5) | constructor(public error: boolean, public msg: string, public data: T) {}
  type STATE_TYPE (line 8) | type STATE_TYPE = {
  class StatesOfACountryResponse (line 12) | class StatesOfACountryResponse {
    method constructor (line 13) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/coupon/CouponService.ts
  class CouponService (line 7) | class CouponService {
    method getAllCouponsAvailableToUserAsync (line 13) | async getAllCouponsAvailableToUserAsync(
    method applyCouponCode (line 83) | async applyCouponCode(couponCode: string): Promise<UserCart | ApiError> {
    method removeCouponCode (line 96) | async removeCouponCode(couponCode: string): Promise<UserCart | ApiErro...

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/coupon/CouponTypes.ts
  type COUPON_TYPES (line 1) | enum COUPON_TYPES {
  class CouponClass (line 5) | class CouponClass {
    method constructor (line 6) | constructor(
  class CouponListClass (line 25) | class CouponListClass {
    method constructor (line 26) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/order/OrderService.ts
  class OrderService (line 10) | class OrderService {
    method generatePayPalOrder (line 14) | async generatePayPalOrder(
    method verifyPayment (line 32) | async verifyPayment(orderId: string): Promise<boolean | ApiError> {
    method getOrderDetail (line 45) | async getOrderDetail(orderId: string): Promise<OrderDetailClass | ApiE...

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/order/OrderTypes.ts
  class GeneratePayPalOrderResponseClass (line 5) | class GeneratePayPalOrderResponseClass {
    method constructor (line 6) | constructor(
  class OrderClass (line 17) | class OrderClass {
    method constructor (line 18) | constructor(
  class OrderListClass (line 42) | class OrderListClass {
    method constructor (line 43) | constructor(
  class OrderItemClass (line 59) | class OrderItemClass {
    method constructor (line 60) | constructor(
  class OrderDetailClass (line 68) | class OrderDetailClass {
    method constructor (line 69) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/product/ProductService.ts
  class ProductService (line 7) | class ProductService {
    method getTopProducts (line 13) | async getTopProducts(
    method getTopOnSaleProducts (line 36) | async getTopOnSaleProducts(
    method getProducts (line 75) | async getProducts(
    method getAllProductsAsync (line 117) | async getAllProductsAsync(
    method getProduct (line 182) | async getProduct(productId: string): Promise<Product | ApiError> {
    method getRelatedProducts (line 196) | async getRelatedProducts(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/product/ProductTypes.ts
  class ImageClass (line 3) | class ImageClass {
    method constructor (line 4) | constructor(
  class Product (line 10) | class Product {
    method constructor (line 11) | constructor(
  class Products (line 30) | class Products {
    method constructor (line 31) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/profile/ProfileService.ts
  class ProfileService (line 7) | class ProfileService {
    method getUserProfile (line 13) | async getUserProfile(): Promise<ProfileClass | ApiError> {
    method updateUserProfile (line 25) | async updateUserProfile(
    method getUsersOrdersAsync (line 47) | async getUsersOrdersAsync(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/services/profile/ProfileTypes.ts
  class ProfileClass (line 3) | class ProfileClass {
    method constructor (line 4) | constructor(

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/store/AuthSlice.ts
  type AuthSliceTypes (line 4) | interface AuthSliceTypes {
  method logIn (line 19) | logIn(state, { payload }) {
  method updateLoginCheckDone (line 23) | updateLoginCheckDone(state, {payload}){
  method logOut (line 26) | logOut() {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/store/BreakpointSlice.ts
  method updateBreakpoint (line 12) | updateBreakpoint(state, {payload}){

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/store/CartSlice.ts
  type CartSliceTypes (line 9) | interface CartSliceTypes {
  type addOrUpdateToCartPayload (line 27) | type addOrUpdateToCartPayload = { productId: string; quantity: number };
  type removeFromCartPayload (line 63) | type removeFromCartPayload = { productId: string };
  method updateAddToCartInProgress (line 109) | updateAddToCartInProgress(state, { payload }) {
  method updateRemoveFromCartInProgress (line 112) | updateRemoveFromCartInProgress(state, { payload }) {
  method updateUserCart (line 115) | updateUserCart(state, {payload}){
  method resetCartSlice (line 118) | resetCartSlice() {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/store/LanguageSlice.ts
  method changeLanguage (line 14) | changeLanguage(state, {payload}) {
  method reset (line 19) | reset(state){

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/store/ToastMessageSlice.ts
  type ToastMessageSliceTypes (line 5) | interface ToastMessageSliceTypes {
  method addMessage (line 38) | addMessage(state, { payload }) {
  method removeMessage (line 43) | removeMessage(state) {

FILE: examples/apps/ecommerce/web/react-vite-redux-tailwind/src/store/index.ts
  type ReduxRootState (line 19) | type ReduxRootState = ReturnType<typeof store.getState>
  type ReduxDispatch (line 22) | type ReduxDispatch = typeof store.dispatch;

FILE: examples/apps/todo/web/react-vite-tailwind/src/App.tsx
  function App (line 14) | function App() {

FILE: examples/apps/todo/web/react-vite-tailwind/src/interfaces/api.ts
  type FreeAPISuccessResponseInterface (line 1) | interface FreeAPISuccessResponseInterface {

FILE: examples/apps/todo/web/react-vite-tailwind/src/interfaces/todo.ts
  type TodoInterface (line 1) | interface TodoInterface {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/App.tsx
  function App (line 5) | function App() {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/components/ui/button.tsx
  type ButtonProps (line 37) | interface ButtonProps

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/components/ui/command.tsx
  type CommandDialogProps (line 24) | interface CommandDialogProps extends DialogProps {}

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/constants/types.ts
  type MappingType (line 2) | interface MappingType {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/layout/header/Header.tsx
  function Header (line 10) | function Header() {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/layout/header/menuItem.ts
  type MenuItem (line 1) | interface MenuItem {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/layout/pageContainer/PageContainer.tsx
  type PageContainerProps (line 4) | interface PageContainerProps {
  function PageContainer (line 9) | function PageContainer(props: PageContainerProps) {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/lib/utils.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/codesList/CodesList.tsx
  function CodesList (line 5) | function CodesList() {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/codesList/components/StatusAccordian.tsx
  function StatusAccordian (line 9) | function StatusAccordian(props: StatusAccordianType) {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/codesList/components/types.ts
  type StatusAccordianType (line 1) | interface StatusAccordianType {
  type StatusListType (line 12) | interface StatusListType {
  type codesType (line 16) | interface codesType {
  type colorCodeMappingType (line 24) | interface colorCodeMappingType {
  type categoryNumberMappingType (line 27) | interface categoryNumberMappingType {
  type categoryDescriptionMappingType (line 31) | interface categoryDescriptionMappingType {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/findCode/FindCode.tsx
  function FindCode (line 9) | function FindCode() {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/findCode/components/ComboBox.tsx
  type optionsTypes (line 18) | interface optionsTypes {
  type ComboBoxProps (line 26) | interface ComboBoxProps {
  function ComboBox (line 35) | function ComboBox(props: ComboBoxProps) {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/home/Home.tsx
  function Home (line 6) | function Home() {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/quiz/Quiz.tsx
  type QuizQuestion (line 8) | interface QuizQuestion {
  function generateQuizFromStatusCodesList (line 13) | function generateQuizFromStatusCodesList(HTTPStatusCodesList: StatusList...
  function Quiz (line 78) | function Quiz() {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/pages/quiz/components/QuestionsCard.tsx
  type QuizQuestion (line 11) | interface QuizQuestion {
  function QuestionsCard (line 22) | function QuestionsCard(props: QuizQuestion) {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/router/routes.ts
  type AppRouteType (line 4) | interface AppRouteType {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/services/codesList.ts
  function processCodes (line 8) | async function processCodes(): Promise<StatusListType> {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/services/types.ts
  type StatusAccordianType (line 1) | interface StatusAccordianType {
  type StatusListType (line 12) | interface StatusListType {
  type codesType (line 16) | interface codesType {

FILE: examples/kitchen-sink/statuscodes/web/react-shadcn-tailwind-zustand/src/store/store.ts
  type StoreType (line 5) | interface StoreType {

FILE: src/constants.js
  constant USER_TEMPORARY_TOKEN_EXPIRY (line 66) | const USER_TEMPORARY_TOKEN_EXPIRY = 20 * 60 * 1000;
  constant MAXIMUM_SUB_IMAGE_COUNT (line 68) | const MAXIMUM_SUB_IMAGE_COUNT = 4;
  constant MAXIMUM_SOCIAL_POST_IMAGE_COUNT (line 69) | const MAXIMUM_SOCIAL_POST_IMAGE_COUNT = 6;
  constant DB_NAME (line 71) | const DB_NAME = "freeapi";

FILE: src/controllers/kitchen-sink/statuscode.controllers.js
  constant CONFLICTING_STATUS_CODES (line 9) | const CONFLICTING_STATUS_CODES = [100, 102, 103, 204, 205, 304];

FILE: src/seeds/_constants.js
  constant TODOS_COUNT (line 2) | const TODOS_COUNT = 20;
  constant USERS_COUNT (line 5) | const USERS_COUNT = 50;
  constant CATEGORIES_COUNT (line 8) | const CATEGORIES_COUNT = 25;
  constant ADDRESSES_COUNT (line 9) | const ADDRESSES_COUNT = 100;
  constant COUPONS_COUNT (line 10) | const COUPONS_COUNT = 15;
  constant PRODUCTS_COUNT (line 11) | const PRODUCTS_COUNT = 50;
  constant PRODUCTS_SUB_IMAGES_COUNT (line 12) | const PRODUCTS_SUB_IMAGES_COUNT = 4;
  constant ORDERS_COUNT (line 13) | const ORDERS_COUNT = 20;
  constant ORDERS_RANDOM_ITEMS_COUNT (line 14) | const ORDERS_RANDOM_ITEMS_COUNT = 20;
  constant SOCIAL_POSTS_COUNT (line 17) | const SOCIAL_POSTS_COUNT = 200;
  constant SOCIAL_POST_IMAGES_COUNT (line 18) | const SOCIAL_POST_IMAGES_COUNT = 6;
  constant SOCIAL_LIKES_COUNT (line 19) | const SOCIAL_LIKES_COUNT = 2000;
  constant SOCIAL_FOLLOWS_COUNT (line 20) | const SOCIAL_FOLLOWS_COUNT = 1000;
  constant SOCIAL_COMMENTS_COUNT (line 21) | const SOCIAL_COMMENTS_COUNT = 500;
  constant SOCIAL_BOOKMARKS_COUNT (line 22) | const SOCIAL_BOOKMARKS_COUNT = 200;
  constant ONE_ON_ONE_CHATS_COUNT (line 25) | const ONE_ON_ONE_CHATS_COUNT = 100;
  constant GROUP_CHATS_COUNT (line 26) | const GROUP_CHATS_COUNT = 30;
  constant GROUP_CHAT_MAX_PARTICIPANTS_COUNT (line 27) | const GROUP_CHAT_MAX_PARTICIPANTS_COUNT = 10;

FILE: src/utils/ApiError.js
  class ApiError (line 6) | class ApiError extends Error {
    method constructor (line 14) | constructor(

FILE: src/utils/ApiResponse.js
  class ApiResponse (line 1) | class ApiResponse {
    method constructor (line 2) | constructor(statusCode, data, message = "Success") {
Condensed preview — 548 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (9,818K chars).
[
  {
    "path": ".babelrc",
    "chars": 95,
    "preview": "{\n  \"presets\": [\"@babel/preset-env\"],\n  \"plugins\": [\"@babel/plugin-syntax-import-assertions\"]\n}"
  },
  {
    "path": ".commitlintrc.json",
    "chars": 319,
    "preview": "{\n  \"extends\": [\"@commitlint/config-conventional\"],\n  \"rules\": {\n    \"type-enum\": [\n      2,\n      \"always\",\n      [\n   "
  },
  {
    "path": ".dockerignore",
    "chars": 22,
    "preview": "/.vscode\n/node_modules"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yaml",
    "chars": 1675,
    "preview": "name: 🐞 Bug report\ndescription: Create a report to help us improve\ntitle: \"BUG: <title>\"\n\nlabels:\n  - bug\n\nbody:\n  - typ"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/code_coverage.yaml",
    "chars": 613,
    "preview": "name: 🧪 Testing Contribution\ndescription: Share details about your test coverage for contribution to FreeAPI.\ntitle: \"TE"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 370,
    "preview": "blank_issues_enabled: true\ncontact_links:\n  - name: FreeAPI Discord Server\n    url: https://hitesh.ai/discord\n    about:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yaml",
    "chars": 1238,
    "preview": "name: 🌟 Feature Request\ndescription: Suggest an enhancement, new feature or anything\ntitle: \"FEATURE: <title>\"\n\nlabels:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/frontend_contribution.yaml",
    "chars": 1599,
    "preview": "name: 🚀 Frontend Contribution\ndescription: Share details about your frontend application for contribution to FreeAPI.\nti"
  },
  {
    "path": ".gitignore",
    "chars": 2384,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n.pnpm-debug.log*\n\n# Diagnostic reports"
  },
  {
    "path": ".husky/commit-msg",
    "chars": 88,
    "preview": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nnpx --no-install commitlint --edit\n"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 83,
    "preview": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nnpx lint-staged --allow-empty\n"
  },
  {
    "path": ".lintstagedrc",
    "chars": 45,
    "preview": "{\n  \"**/*.{js,json}\": [\"prettier --write\"]\n}\n"
  },
  {
    "path": ".prettierignore",
    "chars": 62,
    "preview": "/.vscode\n/node_modules\n./dist\n\n*.yml\n*.yaml\n\n*.env\n.env\n.env.*"
  },
  {
    "path": ".prettierrc",
    "chars": 112,
    "preview": "{\n  \"singleQuote\": false,\n  \"bracketSpacing\": true,\n  \"tabWidth\": 2,\n  \"trailingComma\": \"es5\",\n  \"semi\": true\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 6096,
    "preview": "# Contributing to FreeAPI\n\nThank you for your interest in contributing to FreeAPI! We welcome contributions from the sof"
  },
  {
    "path": "CONTRIBUTING_CODE_COVERAGE.md",
    "chars": 5504,
    "preview": "# FreeAPI Testing Contribution Guide\n\nThank you for your interest in contributing to the FreeAPI project to help us deli"
  },
  {
    "path": "CONTRIBUTING_FRONTEND.md",
    "chars": 10796,
    "preview": "# FreeAPI Frontend Contribution Guide\n\nThank you for your interest in contributing to the FreeAPI project by creating fr"
  },
  {
    "path": "Dockerfile",
    "chars": 454,
    "preview": "FROM node:20.13.1-alpine\n\nRUN mkdir -p /usr/src/freeapi && chown -R node:node /usr/src/freeapi\n\nWORKDIR /usr/src/freeapi"
  },
  {
    "path": "LICENSE.md",
    "chars": 1082,
    "preview": "MIT License\n\nFreeAPI\n\nCopyright (c) 2023 Hitesh Choudhary\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "README.md",
    "chars": 14348,
    "preview": "# FreeAPI.app\n\n## Problem\n\nWe are trying to build a single source API hub that can be used to learn api handling in any "
  },
  {
    "path": "docker-compose.prod.yml",
    "chars": 466,
    "preview": "version: '3.8'\n\nservices:\n  backend:\n    image: freeapi-server\n    build: .\n    ports:\n      - 8080:8080\n    volumes:\n  "
  },
  {
    "path": "docker-compose.yml",
    "chars": 384,
    "preview": "version: '3.8'\n\nservices:\n  backend:\n    image: freeapi-server\n    build: .\n    ports:\n      - 8080:8080\n    volumes:\n  "
  },
  {
    "path": "e2e/common.js",
    "chars": 247,
    "preview": "import dotenv from \"dotenv\";\n\ndotenv.config({\n  path: \"../.env\",\n});\n\nexport const URL = `http://localhost:${process.env"
  },
  {
    "path": "e2e/db.js",
    "chars": 1223,
    "preview": "import mongoose, { mongo } from \"mongoose\";\nimport { MongoMemoryServer } from \"mongodb-memory-server\";\n\nconst MONGO_MEMO"
  },
  {
    "path": "e2e/routes/apps/todo.test.js",
    "chars": 4967,
    "preview": "import { test, expect } from \"@playwright/test\";\nimport { getApiContext } from \"../../common.js\";\nimport { clearDB } fro"
  },
  {
    "path": "e2e/routes/healthcheck.test.js",
    "chars": 477,
    "preview": "import { test, expect } from \"@playwright/test\";\nimport { getApiContext } from \"../common.js\";\n\nlet apiContext;\n\ntest.de"
  },
  {
    "path": "e2e/routes/seeds/chat-app.test.js",
    "chars": 642,
    "preview": "import { test, expect } from \"@playwright/test\";\nimport { getApiContext } from \"../../common.js\";\nimport { clearDB } fro"
  },
  {
    "path": "e2e/routes/seeds/ecommerce.test.js",
    "chars": 2071,
    "preview": "import { test, expect } from \"@playwright/test\";\nimport { getApiContext } from \"../../common.js\";\nimport { clearDB } fro"
  },
  {
    "path": "e2e/routes/seeds/generated-credentials.test.js",
    "chars": 956,
    "preview": "import fs from \"fs\";\nimport { test, expect } from \"@playwright/test\";\nimport { getApiContext } from \"../../common.js\";\n\n"
  },
  {
    "path": "e2e/routes/seeds/social-media.test.js",
    "chars": 1391,
    "preview": "import { test, expect } from \"@playwright/test\";\nimport { getApiContext } from \"../../common.js\";\nimport { clearDB } fro"
  },
  {
    "path": "e2e/routes/seeds/todo.test.js",
    "chars": 1229,
    "preview": "import { test, expect } from \"@playwright/test\";\nimport { getApiContext } from \"../../common.js\";\nimport { clearDB } fro"
  },
  {
    "path": "e2e/test-server.js",
    "chars": 955,
    "preview": "import dotenv from \"dotenv\";\ndotenv.config({\n  path: \"../.env\",\n});\nimport { httpServer } from \"../src/app.js\";\nimport c"
  },
  {
    "path": "examples/apps/auth/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/.eslintrc.cjs",
    "chars": 488,
    "preview": "module.exports = {\n  root: true,\n  env: { browser: true, es2020: true },\n  extends: [\n    \"eslint:recommended\",\n    \"plu"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/.gitignore",
    "chars": 252,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/README.md",
    "chars": 258,
    "preview": "# Installation and setup\n\nCreate a `.env` file in the ROOT folder and copy past the content of the `.env.sample` file in"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/index.html",
    "chars": 402,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/package.json",
    "chars": 1098,
    "preview": "{\n  \"name\": \"vite-chat-app\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vit"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/postcss.config.js",
    "chars": 81,
    "preview": "export default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/App.tsx",
    "chars": 1770,
    "preview": "// Importing required modules and components from the react-router-dom and other files.\nimport { Routes, Route, Navigate"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/api/index.ts",
    "chars": 3195,
    "preview": "// Import necessary modules and utilities\nimport axios from \"axios\";\nimport { LocalStorage } from \"../utils\";\n\n// Create"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/Button.tsx",
    "chars": 1193,
    "preview": "import React from \"react\";\nimport { classNames } from \"../utils\";\n\nconst Button: React.FC<\n  React.ButtonHTMLAttributes<"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/Input.tsx",
    "chars": 452,
    "preview": "import React from \"react\";\nimport { classNames } from \"../utils\";\n\nconst Input: React.FC<React.InputHTMLAttributes<HTMLI"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/Loader.tsx",
    "chars": 1040,
    "preview": "const Loader = () => {\n  return (\n    <div className=\"flex space-x-2 w-full h-screen fixed inset-0 bg-zinc-700/50 z-50 j"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/PrivateRoute.tsx",
    "chars": 888,
    "preview": "// Import required modules and types from React and react-router-dom libraries\nimport React, { ReactNode } from \"react\";"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/PublicRoute.tsx",
    "chars": 778,
    "preview": "// Import necessary libraries and types\nimport React, { ReactNode } from \"react\";\nimport { Navigate } from \"react-router"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/Select.tsx",
    "chars": 3319,
    "preview": "import { Combobox } from \"@headlessui/react\";\nimport { CheckIcon, ChevronUpDownIcon } from \"@heroicons/react/20/solid\";\n"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/AddChatModal.tsx",
    "chars": 13209,
    "preview": "import { Dialog, Switch, Transition } from \"@headlessui/react\";\nimport {\n  UserGroupIcon,\n  XCircleIcon,\n  XMarkIcon,\n} "
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/ChatItem.tsx",
    "chars": 6510,
    "preview": "import {\n  EllipsisVerticalIcon,\n  PaperClipIcon,\n  TrashIcon,\n} from \"@heroicons/react/20/solid\";\nimport { InformationC"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/GroupChatDetailsModal.tsx",
    "chars": 19088,
    "preview": "import { Dialog, Transition } from \"@headlessui/react\";\nimport {\n  PencilIcon,\n  TrashIcon,\n  UserGroupIcon,\n  UserPlusI"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/MessageItem.tsx",
    "chars": 8217,
    "preview": "import {\n  ArrowDownTrayIcon,\n  EllipsisVerticalIcon,\n  MagnifyingGlassPlusIcon,\n  PaperClipIcon,\n  TrashIcon,\n  XMarkIc"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/components/chat/Typing.tsx",
    "chars": 499,
    "preview": "import { classNames } from \"../../utils\";\n\nconst Typing = () => {\n  return (\n    <div\n      className={classNames(\n     "
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/context/AuthContext.tsx",
    "chars": 3506,
    "preview": "import React, { createContext, useContext, useEffect, useState } from \"react\";\nimport { useNavigate } from \"react-router"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/context/SocketContext.tsx",
    "chars": 1603,
    "preview": "/* eslint-disable react-refresh/only-export-components */\nimport React, { createContext, useContext, useEffect, useState"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/index.css",
    "chars": 930,
    "preview": "@import url(\"https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/api.ts",
    "chars": 127,
    "preview": "export interface FreeAPISuccessResponseInterface {\n  data: any;\n  message: string;\n  statusCode: number;\n  success: bool"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/chat.ts",
    "chars": 554,
    "preview": "import { UserInterface } from \"./user\";\n\nexport interface ChatListItemInterface {\n  admin: string;\n  createdAt: string;\n"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/interfaces/user.ts",
    "chars": 203,
    "preview": "export interface UserInterface {\n  _id: string;\n  avatar: {\n    url: string;\n    localPath: string;\n    _id: string;\n  }"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/main.tsx",
    "chars": 551,
    "preview": "import React from \"react\";\nimport ReactDOM from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./index.css\";\ni"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/pages/chat.tsx",
    "chars": 25823,
    "preview": "import {\n  PaperAirplaneIcon,\n  PaperClipIcon,\n  XCircleIcon,\n} from \"@heroicons/react/20/solid\";\nimport { useEffect, us"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/pages/login.tsx",
    "chars": 2306,
    "preview": "// Importing necessary components and hooks\nimport { LockClosedIcon } from \"@heroicons/react/20/solid\";\nimport { useStat"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/pages/register.tsx",
    "chars": 2515,
    "preview": "// Import necessary components and hooks\nimport { LockClosedIcon } from \"@heroicons/react/20/solid\";\nimport { useState }"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/utils/index.ts",
    "chars": 4437,
    "preview": "// Importing necessary modules and interfaces\nimport { AxiosResponse } from \"axios\";\nimport { FreeAPISuccessResponseInte"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/src/vite-env.d.ts",
    "chars": 38,
    "preview": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/tailwind.config.js",
    "chars": 338,
    "preview": "/** @type {import('tailwindcss').Config} */\nexport default {\n  content: [\"./index.html\", \"./src/**/*.{js,ts,jsx,tsx}\"],\n"
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/tsconfig.json",
    "chars": 605,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM."
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/tsconfig.node.json",
    "chars": 213,
    "preview": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"skipLibCheck\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\""
  },
  {
    "path": "examples/apps/chat-app/web/react-vite-tailwind/vite.config.ts",
    "chars": 285,
    "preview": "import { defineConfig } from \"vite\";\nimport dns from \"dns\";\nimport react from \"@vitejs/plugin-react\";\n\ndns.setDefaultRes"
  },
  {
    "path": "examples/apps/ecommerce/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/.eslintrc.cjs",
    "chars": 436,
    "preview": "module.exports = {\n  root: true,\n  env: { browser: true, es2020: true },\n  extends: [\n    'eslint:recommended',\n    'plu"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/.gitignore",
    "chars": 265,
    "preview": ".env\nserver\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modu"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/README.md",
    "chars": 2957,
    "preview": "## ecommerce frontend application\n\nThis is an ecommerce client app which is made by consuming freeapi: https://github.co"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/index.html",
    "chars": 710,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/package.json",
    "chars": 1411,
    "preview": "{\n  \"name\": \"client_app\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\","
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/postcss.config.js",
    "chars": 81,
    "preview": "export default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/public/locales/ar/translation.json",
    "chars": 6403,
    "preview": "{\n  \"en\": \"english\",\n  \"ar\": \"عربي\",\n  \"hn\": \"हिन्दी\",\n  \"select\": \"يختار\",\n  \"infoHeaderMessage\": \"\",\n  \"companyName\": "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/public/locales/en/translation.json",
    "chars": 6430,
    "preview": "{\n  \"en\": \"english\",\n  \"ar\": \"عربي\",\n  \"hn\": \"हिन्दी\",\n  \"select\": \"Select\",\n  \"infoHeaderMessage\": \"\",\n  \"companyName\":"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/public/locales/hn/translation.json",
    "chars": 6406,
    "preview": "{\n  \"en\": \"english\",\n  \"ar\": \"عربي\",\n  \"hn\": \"हिन्दी\",\n  \"select\": \"चुनना\",\n  \"infoHeaderMessage\": \"\",\n  \"companyName\": "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/App.tsx",
    "chars": 105,
    "preview": "import RoutePaths from \"./RoutePaths\";\n\nfunction App() {\n  return <RoutePaths />;\n}\n\nexport default App;\n"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/RoutePaths.tsx",
    "chars": 3252,
    "preview": "import { BrowserRouter, Route, Routes } from \"react-router-dom\";\nimport PageLayout from \"./layouts/PageLayout\";\nimport H"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/ArrowButton.tsx",
    "chars": 1148,
    "preview": "import { useMemo } from \"react\";\nimport { ARROW_BUTTONS } from \"../../constants\";\nimport UpArrow from \"../icons/UpArrow\""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Button.tsx",
    "chars": 1501,
    "preview": "import { ReactElement, useMemo } from \"react\";\nimport { ButtonTypes } from \"../../constants\";\nimport LoadingSpinner from"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/CarouselButtons.tsx",
    "chars": 2775,
    "preview": "import { RefObject, useCallback, useEffect, useState } from \"react\";\nimport { useAppSelector } from \"../../store\";\nimpor"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Checkbox.tsx",
    "chars": 4102,
    "preview": "import React, { useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { CHECKBOX_TY"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/DateRangePicker.tsx",
    "chars": 4317,
    "preview": "import { ar } from \"date-fns/locale/ar\";\nimport { enIN } from \"date-fns/locale/en-IN\";\nimport React, { useEffect, useMem"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Drawer.tsx",
    "chars": 2352,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { DrawerOption, NavigationOption } from \"../../constants\";\nimport"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Dropdown.tsx",
    "chars": 6684,
    "preview": "import {\n  ForwardedRef,\n  forwardRef,\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState\n} from \"react\";\nimpor"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/ErrorMessage.tsx",
    "chars": 851,
    "preview": "import { useAppSelector } from \"../../store\";\nimport ErrorIcon from \"../icons/ErrorIcon\";\n\n\ninterface ErrorMessageProps "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/FullPageLoadingSpinner.tsx",
    "chars": 506,
    "preview": "import LoadingSpinner from \"../icons/LoadingSpinner\";\nimport { createPortal } from \"react-dom\";\n\nconst FullPageLoadingSp"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Hamburger.tsx",
    "chars": 1858,
    "preview": "import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useLocation } from \"react-router-dom\";\nimport"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Image.tsx",
    "chars": 592,
    "preview": "import { SyntheticEvent } from \"react\";\n\ninterface ImageProps {\n    src: string,\n    alt: string,\n    backupImageSrc: st"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Input.tsx",
    "chars": 2839,
    "preview": "import { ForwardedRef, forwardRef, useId, useState } from \"react\";\nimport { useAppSelector } from \"../../store\";\nimport "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Link.tsx",
    "chars": 820,
    "preview": "import { useMemo } from \"react\";\nimport { LinkTypes } from \"../../constants\";\nimport { useAppSelector } from \"../../stor"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Modal.tsx",
    "chars": 2554,
    "preview": "import { useMemo } from \"react\";\nimport { ButtonTypes } from \"../../constants\";\nimport Button from \"./Button\";\n\ninterfac"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/NavItem.tsx",
    "chars": 1415,
    "preview": "import { NavLink, useLocation } from \"react-router-dom\";\nimport { NavigationOption } from \"../../constants\";\nimport { us"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/NavList.tsx",
    "chars": 782,
    "preview": "import { NavigationOption } from \"../../constants\";\nimport { useAppSelector } from \"../../store\";\nimport NavItem from \"."
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/RadioButtons.tsx",
    "chars": 2209,
    "preview": "import React, { useId } from \"react\";\nimport { RADIO_BUTTON_TYPE } from \"../../constants\";\nimport { useAppSelector } fro"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/RoundedIcon.tsx",
    "chars": 304,
    "preview": "interface RoundedIconProps {\n  icon: React.ReactElement;\n}\nconst RoundedIcon = (props: RoundedIconProps) => {\n  const { "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/SearchInput.tsx",
    "chars": 1687,
    "preview": "import { FormEvent, useState } from \"react\";\nimport SearchIcon from \"../icons/SearchIcon\";\nimport { useAppSelector } fro"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/SelectionMenu.tsx",
    "chars": 2827,
    "preview": "import { useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { BREAKPOINT"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/TabItem.tsx",
    "chars": 789,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { TabItemConfig } from \"../../constants\";\nimport Text from \"./Tex"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Tabs.tsx",
    "chars": 1493,
    "preview": "import { useState } from \"react\";\nimport { TabItemConfig } from \"../../constants\";\nimport TabItem from \"./TabItem\";\nimpo"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/Text.tsx",
    "chars": 394,
    "preview": "import { useAppSelector } from \"../../store\";\n\ninterface TextProps {\n  className?: string;\n  children: string;\n}\nconst T"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/basic/ToastMessage.tsx",
    "chars": 1626,
    "preview": "import { useMemo } from \"react\";\nimport { TOAST_MESSAGE_TYPES } from \"../../constants\";\nimport { useAppSelector } from \""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/AddressCard.tsx",
    "chars": 2419,
    "preview": "import { useState } from \"react\";\nimport { AddressClass } from \"../../services/address/AddressTypes\";\nimport Button from"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/AddressCardList.tsx",
    "chars": 849,
    "preview": "import { AddressClass } from \"../../services/address/AddressTypes\";\nimport AddressCard from \"./AddressCard\";\n\ninterface "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CardContainer.tsx",
    "chars": 2926,
    "preview": "import { RefObject } from \"react\";\nimport { ButtonTypes, CARD_CONTAINER_OPTION } from \"../../constants\";\nimport Rectangl"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CartItem.tsx",
    "chars": 2949,
    "preview": "import { useMemo } from \"react\";\nimport { PUBLIC_IMAGE_PATHS } from \"../../constants\";\nimport { CartItemClass } from \".."
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CartItemList.tsx",
    "chars": 802,
    "preview": "import { CartItemClass } from \"../../services/cart/CartTypes\";\nimport { Product } from \"../../services/product/ProductTy"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CartSummary.tsx",
    "chars": 1389,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { ButtonTypes } from \"../../constants\";\nimport { UserCart } from "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CategoryCard.tsx",
    "chars": 995,
    "preview": "import { CATEGORY_ICONS } from \"../../data/applicationData\";\nimport { Category } from \"../../services/category/CategoryT"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CompanyGurantee.tsx",
    "chars": 648,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { COMPANY_GURANTEE } from \"../../constants\";\nimport RoundedIcon f"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CouponCard.tsx",
    "chars": 709,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { CouponClass } from \"../../services/coupon/CouponTypes\";\n\ninterf"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/CouponCardList.tsx",
    "chars": 881,
    "preview": "import { CouponClass } from \"../../services/coupon/CouponTypes\";\nimport { useAppSelector } from \"../../store\";\nimport Co"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/FooterSection.tsx",
    "chars": 601,
    "preview": "import Text from \"../basic/Text\"\n\n\ninterface FooterSectionProps {\n    heading: string,\n    children?: React.ReactElement"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/InvoiceAmountSummary.tsx",
    "chars": 1439,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { useAppSelector } from \"../../store\";\nimport { formatAmount } fr"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderCard.tsx",
    "chars": 2338,
    "preview": "import { useMemo } from \"react\";\nimport { OrderClass } from \"../../services/order/OrderTypes\";\nimport { convertUTCToLoca"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderItem.tsx",
    "chars": 1758,
    "preview": "import { useMemo } from \"react\";\nimport { PUBLIC_IMAGE_PATHS } from \"../../constants\";\nimport { OrderItemClass } from \"."
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderItemList.tsx",
    "chars": 499,
    "preview": "import { OrderItemClass } from \"../../services/order/OrderTypes\";\nimport OrderItem from \"./OrderItem\";\n\ninterface OrderI"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderListFilters.tsx",
    "chars": 3347,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport Button from \"../basic/Button\";\nimport DateRangePicker, {\n  DateRa"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrderSummary.tsx",
    "chars": 1056,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { OrderDetailClass } from \"../../services/order/OrderTypes\";\nimpo"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/OrdersList.tsx",
    "chars": 1189,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { OrderClass } from \"../../services/order/OrderTypes\";\nimport { u"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/Payment.tsx",
    "chars": 2235,
    "preview": "import { PayPalButtons, PayPalScriptProvider } from \"@paypal/react-paypal-js\";\nimport { useEffect, useMemo, useRef } fro"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductCard.tsx",
    "chars": 2419,
    "preview": "import { Product } from \"../../services/product/ProductTypes\";\nimport Image from \"../basic/Image\";\nimport { DEFAULT_CURR"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductFilters.tsx",
    "chars": 3189,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { ButtonTypes, ProductFilterFields } from \"../../constants\";\nimpo"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductImagesView.tsx",
    "chars": 2427,
    "preview": "import { useEffect, useState } from \"react\";\nimport { ImageClass } from \"../../services/product/ProductTypes\";\nimport Im"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/ProductList.tsx",
    "chars": 768,
    "preview": "import { Product } from \"../../services/product/ProductTypes\";\nimport { useAppSelector } from \"../../store\";\nimport Prod"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/QuantityCounter.tsx",
    "chars": 2395,
    "preview": "import { useEffect, useMemo, useState } from \"react\";\nimport AddIcon from \"../icons/AddIcon\";\nimport SubtractIcon from \""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/business/Timer.tsx",
    "chars": 3119,
    "preview": "import moment from \"moment\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { DATE_TIME_FORMATS, DURAT"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/AccountIcon.tsx",
    "chars": 888,
    "preview": "const AccountIcon = (props: { className: string }) => {\n  const { className = \"\" } = props;\n  return (\n    <svg\n      xm"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/AddIcon.tsx",
    "chars": 420,
    "preview": "const AddIcon = (props: { className: string }) => {\n  const { className } = props;\n  return (\n    <svg\n      xmlns=\"http"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/CartIcon.tsx",
    "chars": 2017,
    "preview": "import { useAppSelector } from \"../../store\";\n\nconst CartIcon = (props: { className: string; quantity?: number }) => {\n "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/CloseIcon.tsx",
    "chars": 427,
    "preview": "const CloseIcon = ({className}: { className: string }) => {\n  return (\n    <svg\n      className={className}\n      xmlns="
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/DeleteIcon.tsx",
    "chars": 435,
    "preview": "const DeleteIcon = (props: { className: string }) => {\n  const { className } = props;\n\n  return (\n    <svg\n      classNa"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/DownArrow.tsx",
    "chars": 487,
    "preview": "const DownArrow = (props: { className?: string }) => {\n  const { className } = props;\n  return (\n    <svg\n      classNam"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/EditIcon.tsx",
    "chars": 1248,
    "preview": "const EditIcon = (props: { className: string }) => {\n  const { className = \"\" } = props;\n\n  return (\n    <svg\n      xmln"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/ErrorIcon.tsx",
    "chars": 524,
    "preview": "const ErrorIcon = (props: { className: string }) => {\n  const { className } = props;\n  return (\n    <svg viewBox=\"0 0 32"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/GeneralCategoryIcon.tsx",
    "chars": 2076,
    "preview": "const GeneralCategoryIcon = (props: { className: string }) => {\n  const { className } = props;\n  return (\n    <svg\n     "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/GoogleIcon.tsx",
    "chars": 1314,
    "preview": "const GoogleIcon = (props: { className: string }) => {\n  const { className = \"\" } = props;\n  return (\n    <svg\n      xml"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/GuranteeIcon.tsx",
    "chars": 2453,
    "preview": "const GuranteeIcon = (props: {className: string}) => {\n    const {className} = props\n  return (\n    <svg\n      xmlns=\"ht"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/HamburgerIcon.tsx",
    "chars": 424,
    "preview": "const HamburgerIcon = ({className}: { className: string }) => {\n  return (\n    <svg\n      className={className}\n      xm"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/HeadphoneIcon.tsx",
    "chars": 1866,
    "preview": "const HeadphoneIcon = (props: {className: string}) => {\n    const {className} = props\n  return (\n    <svg\n      xmlns=\"h"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/HidePasswordIcon.tsx",
    "chars": 818,
    "preview": "const HidePasswordIcon = (props: { className: string }) => {\n  const { className } = props;\n  return (\n    <svg\n      cl"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/LeftArrow.tsx",
    "chars": 443,
    "preview": "const LeftArrow = (props: { className: string }) => {\n  const { className } = props;\n  return (\n    <svg\n      xmlns=\"ht"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/LoadingSpinner.tsx",
    "chars": 1376,
    "preview": "const LoadingSpinner = ({className}: { className: string }) => {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      clas"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/LogoutIcon.tsx",
    "chars": 772,
    "preview": "const LogoutIcon = (props: { className: string }) => {\n  const { className = \"\" } = props;\n\n  return (\n    <svg\n      xm"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/OrderIcon.tsx",
    "chars": 813,
    "preview": "const OrderIcon = (props: { className: string }) => {\n  const { className = '' } = props;\n  return (\n    <svg\n      view"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/RectangleIcon.tsx",
    "chars": 380,
    "preview": "const RectangleIcon = (props: {className: string, rectClassName: string}) => {\n    const {className, rectClassName} =pro"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/SearchIcon.tsx",
    "chars": 779,
    "preview": "const SearchIcon = (props: { className: string }) => {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/ShowPasswordIcon.tsx",
    "chars": 862,
    "preview": "const ShowPasswordIcon = (props: { className: string }) => {\n  const { className } = props;\n  return (\n    <svg\n      cl"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/SubtractIcon.tsx",
    "chars": 404,
    "preview": "const SubtractIcon = (props: { className: string }) => {\n  const { className } = props;\n  return (\n    <svg\n      xmlns="
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/TickIcon.tsx",
    "chars": 627,
    "preview": "const TickIcon = (props: {\n  className: string;\n  circleProps?: { cx: number; cy: number; r: number; className: string }"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/TruckIcon.tsx",
    "chars": 2763,
    "preview": "const TruckIcon = (props: {className: string}) => {\n    const {className} = props\n  return (\n    <svg\n      xmlns=\"http:"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/icons/UpArrow.tsx",
    "chars": 436,
    "preview": "const UpArrow = (props: {className: string}) => {\n    const {className} = props\n  return (\n    <svg\n      xmlns=\"http://"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/addaddressmodal/container/AddAddressModalContainer.tsx",
    "chars": 10857,
    "preview": "import { useCallback, useEffect, useReducer, useState } from \"react\";\nimport { COUNTRIES_DROPDOWN_LIST } from \"../../../"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/addaddressmodal/presentation/AddAddressModal.tsx",
    "chars": 8825,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport {\n  ADDRESS_FORM_KEYS,\n  AddressFormFields,\n  ButtonTypes,\n  Drop"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/changepasswordmodal/container/ChangePasswordModalContainer.tsx",
    "chars": 2181,
    "preview": "import { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ChangePasswordFields } from \""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/changepasswordmodal/presentation/ChangePasswordModal.tsx",
    "chars": 3536,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport Modal from \"../../../basic/Modal\";\nimport Button from \"../../../b"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/deleteaddressmodal/container/DeleteAddressModalContainer.tsx",
    "chars": 2015,
    "preview": "import { useState } from \"react\";\nimport DeleteAddressModal from \"../presentation/DeleteAddressModal\";\nimport { AddressC"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/deleteaddressmodal/presentation/DeleteAddressModal.tsx",
    "chars": 1208,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport Modal from \"../../../basic/Modal\";\nimport ErrorMessage from \"../."
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/feedbackmodal/presentation/FeedbackModal.tsx",
    "chars": 1672,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport ErrorMessage from \"../../../basic/ErrorMessage\";\nimport Modal fro"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/forgotpasswordmodal/container/ForgotPasswordModalContainer.tsx",
    "chars": 1956,
    "preview": "import { useState } from \"react\";\nimport ForgotPasswordModal from \"../presentation/ForgotPasswordModal\";\nimport { Forgot"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/forgotpasswordmodal/presentation/ForgotPasswordModal.tsx",
    "chars": 2752,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport {\n  ButtonTypes,\n  ForgotPasswordFields,\n  REGEX_PATTERNS,\n} from"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/logoutmodal/container/LogoutModalContainer.tsx",
    "chars": 1490,
    "preview": "import { useDispatch } from \"react-redux\";\nimport LogoutModal from \"../presentation/LogoutModal\";\nimport useCustomNaviga"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/modals/logoutmodal/presentation/LogoutModal.tsx",
    "chars": 1479,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport Modal from \"../../../basic/Modal\";\nimport ErrorMessage from \"../."
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/about/container/AboutContainer.tsx",
    "chars": 145,
    "preview": "import About from \"../presentation/About\"\n\n\nconst AboutContainer = () => {\n    return (\n        <About />\n    )\n}\n\nexpor"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/about/presentation/About.tsx",
    "chars": 1820,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport Text from \"../../../basic/Text\";\nimport Image from \"../../../basi"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/allproductlist/container/AllProductListContainer.tsx",
    "chars": 5467,
    "preview": "import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/allproductlist/presentation/AllProductList.tsx",
    "chars": 1909,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { Product } from \"../../../../services/product/ProductTypes\";\nimp"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/banner/container/BannerContainer.tsx",
    "chars": 888,
    "preview": "import { useEffect, useState } from \"react\";\nimport { DATE_TIME_FORMATS } from \"../../../../constants\";\nimport { BANNER_"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/banner/presentation/Banner.tsx",
    "chars": 1726,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { useAppSelector } from \"../../../../store\";\nimport Image from \"."
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/cart/container/CartContainer.tsx",
    "chars": 2062,
    "preview": "import { useMemo } from \"react\";\nimport { Product } from \"../../../../services/product/ProductTypes\";\nimport { useAppDis"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/cart/presentation/Cart.tsx",
    "chars": 1304,
    "preview": "import { UserCart } from \"../../../../services/cart/CartTypes\";\nimport { Product } from \"../../../../services/product/Pr"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/categorylist/container/CategoryListContainer.tsx",
    "chars": 1621,
    "preview": "import { useEffect, useState } from \"react\";\nimport CategoryList from \"../presentation/CategoryList\";\nimport { Category "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/categorylist/presentation/CategoryList.tsx",
    "chars": 1675,
    "preview": "import { useRef } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { CARD_CONTAINER_OPTION } from \"."
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/checkout/container/CheckoutContainer.tsx",
    "chars": 4375,
    "preview": "import { useCallback, useEffect, useState } from \"react\";\nimport Checkout from \"../presentation/Checkout\";\nimport { Addr"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/checkout/presentation/Checkout.tsx",
    "chars": 6838,
    "preview": "import { useEffect, useState } from \"react\";\nimport { AddressClass } from \"../../../../services/address/AddressTypes\";\ni"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/companyguranteelist/container/CompanyGuranteeListContainer.tsx",
    "chars": 323,
    "preview": "import { COMPANY_GURANTEE_LIST } from \"../../../../data/applicationData\";\nimport CompanyGuranteeList from \"../presentati"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/companyguranteelist/presentation/CompanyGuranteeList.tsx",
    "chars": 902,
    "preview": "import { COMPANY_GURANTEE } from \"../../../../constants\";\nimport { useAppSelector } from \"../../../../store\";\nimport Com"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/editaddresses/container/EditAddressesContainer.tsx",
    "chars": 1625,
    "preview": "import { useCallback, useEffect, useState } from \"react\";\nimport AddressService from \"../../../../services/address/Addre"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/editaddresses/presentation/EditAddresses.tsx",
    "chars": 1578,
    "preview": "import { useState } from \"react\";\nimport { AddressClass } from \"../../../../services/address/AddressTypes\";\nimport Butto"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/editprofile/container/EditProfileContainer.tsx",
    "chars": 3252,
    "preview": "import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport ApiError from \"../../../../services/ApiError\";"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/editprofile/presentation/EditProfile.tsx",
    "chars": 5042,
    "preview": "import { useEffect, useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { useTranslation } from \""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/exploreproductlist/container/ExploreProductListContainer.tsx",
    "chars": 1326,
    "preview": "import { useEffect, useState } from \"react\";\nimport ExploreProductList from \"../presentation/ExploreProductList\";\nimport"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/exploreproductlist/presentation/ExploreProductList.tsx",
    "chars": 1158,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport CardContainer from \"../../../business/CardContainer\";\nimport { CA"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/featuredproductlist/container/FeaturedProductListContainer.tsx",
    "chars": 1405,
    "preview": "import { useEffect, useState } from \"react\";\nimport { Product } from \"../../../../services/product/ProductTypes\";\nimport"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/featuredproductlist/presentation/FeaturedProductList.tsx",
    "chars": 1152,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport CardContainer from \"../../../business/CardContainer\";\nimport { CA"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/footer/container/FooterContainer.tsx",
    "chars": 150,
    "preview": "import Footer from \"../presentation/Footer\"\n\n\nconst FooterContainer = () => {\n    return (\n        <Footer />\n    )\n}\n\ne"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/footer/presentation/Footer.tsx",
    "chars": 1351,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport FooterSection from \"../../../business/FooterSection\";\nimport { us"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/header/container/HeaderContainer.tsx",
    "chars": 3022,
    "preview": "import React, { ForwardedRef, useCallback, useEffect, useState } from \"react\";\nimport Header from \"../presentation/Heade"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/header/presentation/Header.tsx",
    "chars": 2940,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { BREAKPOINTS, NavigationOption } from \"../../../../constants\";\ni"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/infoheader/container/InfoHeaderContainer.tsx",
    "chars": 2008,
    "preview": "import { useMemo } from \"react\";\nimport InfoHeader from \"../presentation/InfoHeader\";\nimport {\n  DropdownItem,\n  SUPPORT"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/infoheader/presentation/InfoHeader.tsx",
    "chars": 1528,
    "preview": "import {\n  DropdownItem,\n  DropdownTypes,\n} from \"../../../../constants\";\nimport Dropdown from \"../../../basic/Dropdown\""
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/login/container/LoginContainer.tsx",
    "chars": 2582,
    "preview": "import { useState } from \"react\";\nimport { LoginFormFields, ROUTE_PATHS } from \"../../../../constants\";\nimport Login fro"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/login/presentation/Login.tsx",
    "chars": 3653,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport Button from \"../../../basic/Button\";\nimport Input from \"../../../"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/myaccountoption/container/MyAccountOptionContainer.tsx",
    "chars": 1205,
    "preview": "import { ROUTE_PATHS, SelectionMenuItem } from \"../../../../constants\";\nimport MyAccountOption from \"../presentation/MyA"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/myaccountoption/presentation/MyAccountOption.tsx",
    "chars": 730,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { SelectionMenuItem } from \"../../../../constants\";\nimport Select"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/myorderslist/container/MyOrdersListContainer.tsx",
    "chars": 4700,
    "preview": "import { useCallback, useEffect, useState } from \"react\";\nimport ProfileService from \"../../../../services/profile/Profi"
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/myorderslist/presentation/MyOrdersList.tsx",
    "chars": 1215,
    "preview": "import { useTranslation } from \"react-i18next\";\nimport { OrderListFilterFields } from \"../../../../constants\";\nimport { "
  },
  {
    "path": "examples/apps/ecommerce/web/react-vite-redux-tailwind/src/components/widgets/orderdetail/container/OrderDetailContainer.tsx",
    "chars": 1002,
    "preview": "import { useCallback, useEffect, useState } from \"react\";\nimport OrderService from \"../../../../services/order/OrderServ"
  }
]

// ... and 348 more files (download for full content)

About this extraction

This page contains the full source code of the hiteshchoudhary/apihub GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 548 files (8.7 MB), approximately 2.3M tokens, and a symbol index with 371 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!