├── .github └── workflows │ └── git.yml ├── .gitignore ├── LICENSE ├── README.md ├── client ├── .gitignore ├── LICENSE ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── isell-1.png │ ├── isell.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.tsx │ ├── assets │ │ ├── Shadow.png │ │ ├── Shape.png │ │ ├── add.png │ │ ├── asian.png │ │ ├── chart1.png │ │ ├── chart12.png │ │ ├── check-circle.svg │ │ ├── coil.png │ │ ├── country-icon.png │ │ ├── forgot.jpeg │ │ ├── google.png │ │ ├── isell-logo.png │ │ ├── man.png │ │ ├── music.png │ │ ├── person.jpeg │ │ ├── pfp.svg │ │ ├── product-1.png │ │ ├── product1.png │ │ ├── product2.png │ │ ├── product3.png │ │ ├── product4.png │ │ ├── product5.png │ │ ├── profile.png │ │ ├── profilep.png │ │ ├── rapyd-logo.png │ │ ├── setup.jpg │ │ ├── shopping-cart.png │ │ ├── shopping-cart.svg │ │ ├── sign-up.png │ │ ├── upload.png │ │ ├── vector1.png │ │ ├── vector2.png │ │ ├── woman.png │ │ └── young-picture.png │ ├── components │ │ ├── check-out │ │ │ ├── cart-items │ │ │ │ ├── cart-items.scss │ │ │ │ └── cart-items.tsx │ │ │ ├── check-out.components.tsx │ │ │ ├── check-out.scss │ │ │ └── sub-total │ │ │ │ ├── sub-total.scss │ │ │ │ └── sub-total.tsx │ │ ├── dashboard │ │ │ ├── customer-item │ │ │ │ ├── customer-item.scss │ │ │ │ └── customer-item.tsx │ │ │ ├── dashboard-create-products │ │ │ │ ├── dashboard-create.component.tsx │ │ │ │ └── dashboard-create.scss │ │ │ ├── dashboard-customers │ │ │ │ ├── dashboard-customers.scss │ │ │ │ └── dashboard-customers.tsx │ │ │ ├── dashboard-navbar │ │ │ │ ├── dashboard-navbar.component.tsx │ │ │ │ ├── dashboard-navbar.scss │ │ │ │ └── mobile-menu │ │ │ │ │ ├── mobile-menu.scss │ │ │ │ │ └── mobile-menu.tsx │ │ │ ├── dashboard-products │ │ │ │ ├── dashboard-products.component.tsx │ │ │ │ └── dashboard-products.scss │ │ │ ├── dashboard-sales │ │ │ │ └── dashboard-sales.component.tsx │ │ │ ├── dashboard-sidebar │ │ │ │ ├── dashboard-sidebar.component.tsx │ │ │ │ └── dashboard-sidebar.scss │ │ │ ├── dashboard.component.tsx │ │ │ └── dashboard.scss │ │ ├── forgot-password │ │ │ ├── forgot-password.component.tsx │ │ │ └── forgot.scss │ │ ├── home │ │ │ ├── footer │ │ │ │ ├── footer.components.tsx │ │ │ │ └── footer.scss │ │ │ ├── hero-section │ │ │ │ ├── hero-section.components.tsx │ │ │ │ └── hero-section.scss │ │ │ ├── home.component.tsx │ │ │ ├── home.scss │ │ │ ├── navbar │ │ │ │ ├── navbar.component.tsx │ │ │ │ └── navbar.scss │ │ │ ├── splash-section │ │ │ │ ├── splash-section.component.tsx │ │ │ │ └── splash-section.scss │ │ │ ├── sub-footer │ │ │ │ ├── sub-footer.component.tsx │ │ │ │ └── sub-footer.scss │ │ │ └── sub-section │ │ │ │ ├── sub-section.component.tsx │ │ │ │ └── sub-section.scss │ │ ├── login │ │ │ ├── login.component.tsx │ │ │ └── login.scss │ │ ├── product │ │ │ ├── product-display │ │ │ │ ├── product-display.scss │ │ │ │ └── product-display.tsx │ │ │ ├── product-footer │ │ │ │ ├── product-footer.scss │ │ │ │ └── product-footer.tsx │ │ │ ├── product-item │ │ │ │ ├── product-item.scss │ │ │ │ └── product-item.tsx │ │ │ ├── product-items │ │ │ │ ├── product-items.scss │ │ │ │ └── product-items.tsx │ │ │ ├── product.components.tsx │ │ │ └── product.scss │ │ ├── register │ │ │ ├── register.component.tsx │ │ │ └── register.scss │ │ ├── setup │ │ │ ├── setup.business-type.ts │ │ │ ├── setup.component.tsx │ │ │ └── setup.scss │ │ ├── spinner │ │ │ ├── spinner.scss │ │ │ └── spinner.tsx │ │ └── stores │ │ │ ├── store-item │ │ │ ├── store-item.scss │ │ │ └── store-item.tsx │ │ │ ├── stores.scss │ │ │ └── stores.tsx │ ├── firebase │ │ ├── firebase.config.types.ts │ │ └── firebase.utils.ts │ ├── index.d.ts │ ├── index.scss │ ├── index.tsx │ ├── pages │ │ ├── check-out │ │ │ └── check-out.tsx │ │ ├── dashboard │ │ │ └── DashboardPage.tsx │ │ ├── forgot-password │ │ │ └── ForgotPasswordPage.tsx │ │ ├── landing │ │ │ └── LandingPage.tsx │ │ ├── login │ │ │ └── LoginPage.tsx │ │ ├── register │ │ │ └── RegisterPage.tsx │ │ ├── setup │ │ │ └── SetupPage.tsx │ │ └── stores │ │ │ └── stores.tsx │ ├── rapyd-hooks │ │ ├── config.ts │ │ ├── create-checkout.ts │ │ └── create-vendor.wallet.ts │ ├── statics │ │ ├── AlertModal.tsx │ │ └── ErrorMessage.tsx │ ├── store │ │ ├── alert │ │ │ ├── alert.modal.reducer.ts │ │ │ └── alert.modal.types.ts │ │ ├── basket │ │ │ ├── basket-types.ts │ │ │ └── basket.ts │ │ ├── error-message │ │ │ ├── error-message.reducer.ts │ │ │ └── error-message.types.ts │ │ ├── store.ts │ │ └── user │ │ │ ├── user.reducer.ts │ │ │ └── user.types.ts │ └── validation │ │ ├── validation.tsx │ │ └── validation2.tsx └── tsconfig.json ├── package.json └── server ├── .gitignore ├── ProcFile ├── package.json ├── server.ts ├── src ├── controller │ └── utilities.ts └── routes │ ├── checkout.ts │ └── wallet.ts └── tsconfig.json /.github/workflows/git.yml: -------------------------------------------------------------------------------- 1 | 2 | 3 | # This is a basic workflow to help you get started with Actions 4 | 5 | name: Paylancers 💳 6 | 7 | # Controls when the workflow will run 8 | on: 9 | # Triggers the workflow on push or pull request events but only for the "main" branch 10 | push: 11 | branches: [ "main" ] 12 | pull_request: 13 | branches: [ "main" ] 14 | 15 | # Allows you to run this workflow manually from the Actions tab 16 | workflow_dispatch: 17 | 18 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 19 | jobs: 20 | # This workflow contains a single job called "build" 21 | build: 22 | # The type of runner that the job will run on 23 | runs-on: ubuntu-latest 24 | 25 | # Steps represent a sequence of tasks that will be executed as part of the job 26 | steps: 27 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 28 | - uses: actions/checkout@v3 29 | 30 | # Runs a single command using the runners shell 31 | - name: Run a one-line script 32 | run: echo Hello, world! 33 | 34 | # Runs a set of commands using the runners shell 35 | - name: Run a multi-line script 36 | run: | 37 | echo Add other actions to build, 38 | echo test, and deploy your project. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .package-lock.json 2 | package-lock.json 3 | .env 4 | build 5 | node_modules 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 xyz_devs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iSELL 2 | iSELL is a merchant payment web application leveraging rapyd APIs for wallet creation and checkout. 3 | 4 | ![image](https://d112y698adiu2z.cloudfront.net/photos/production/software_photos/002/227/665/datas/original.png) 5 | 6 | Contents 7 | ================= 8 | 9 | * [About](#About) 10 | * [Technologies-&-Tools](#Technologies-&-Tools) 11 | * [Requirements](#Requirements) 12 | * [Run-On-Local-Machine](#Run-On-Local-Machine) 13 | * [Links](#Links) 14 | * [License](#License) 15 | 16 | 17 | About 18 | ============ 19 | We’re building this product to serve the vendors & traders in the Nigerian SME space, they face a series of problem while trying to sell their goods and services, and with iSELL, we plan to solve these problems, and hopefully expand it into other parts of Africa. 20 | 21 | Some of the Problems vendors face in this part of the world is that there’s no centralized location where they can display all the goods and services they have available, using their social media accounts to trade and display goods isn’t scalable and comes with a lot of inconveniences, and using other third-party E-commerce platforms isn’t any better as they come with their own host of problems such as taking a huge percentage from their profits, and with these third-party platforms, there’s no guarantee that visitors would surely buy from your store rather than the hundreds of others there. 22 | 23 | Vendors also have a lot of problems surrounding accepting payments, such as delays in payments and the inability to accept cross-border payments. 24 | 25 | Technologies-&-Tools 26 | ============ 27 | - ReactJS 28 | - NodeJS(ExpressJs) 29 | - TypeScript 30 | - Firebase(Firestore) 31 | - Rapyd API 32 | 33 | Requirements 34 | ============ 35 | * NPM and Node installed, download [HERE](https://phoenixnap.com/kb/install-node-js-npm-on-windows) 36 | * [Create-React-app](https://reactjs.org/docs/create-a-new-react-app.html) must be installed. 37 | 38 | 39 | Run-On-Local-Machine 40 | ============ 41 | * git clone the repository 42 | 43 | ``` 44 | $ git clone https://github.com/Team-xyzdev/iSELL 45 | ``` 46 | * create `.env` file in the client and server directory 47 | 48 | ### Client 49 | 50 | * open `client` in your text editor 51 | 52 | ``` 53 | $ cd client 54 | ``` 55 | 56 | * in your `.env` file 57 | 58 | ``` 59 | REACT_APP_apiKey="put your firebase credential" 60 | REACT_APP_authDomain="put your firebase credential" 61 | REACT_APP_projectId="put your firebase credential" 62 | REACT_APP_storageBucket="put your firebase credential" 63 | REACT_APP_messagingSenderId="put your firebase credential" 64 | REACT_APP_appId="put your firebase credential" 65 | REACT_APP_measurementId="put your firebase credential" 66 | ``` 67 | 68 | - install dependencies 69 | ``` 70 | $ npm install 71 | ``` 72 | - start scripts 73 | 74 | ``` 75 | $ npm start 76 | ``` 77 | 78 | * or with yarn 79 | 80 | - install dependencies 81 | ``` 82 | $ yarn add 83 | ``` 84 | - start scripts 85 | ``` 86 | $ yarn start 87 | ``` 88 | 89 | ### Server 90 | 91 | * open `server` in your text editor 92 | 93 | ``` 94 | $ cd server 95 | ``` 96 | 97 | * in your `.env` file 98 | 99 | ``` 100 | accessKey="// get it by creating a rapyd API account" 101 | secretKey="// get it by creating a rapyd API account" 102 | apirootURL="sandboxapi.rapyd.net" 103 | ``` 104 | 105 | - install dependencies 106 | ``` 107 | $ npm install 108 | ``` 109 | - start scripts 110 | 111 | ``` 112 | $ npm start 113 | ``` 114 | 115 | * or with yarn 116 | 117 | - install dependencies 118 | ``` 119 | $ yarn add 120 | ``` 121 | - start scripts 122 | ``` 123 | $ yarn start 124 | ``` 125 | Links 126 | ============ 127 | * [netlify-link](https://i-sell.netlify.app/) 128 | * [iSELL-PRD](https://drive.google.com/file/d/1rS-kyjRK7UmENlO-NxZ8qRngGw4zNoqP/view?usp=sharing) 129 | * [Devpost](https://devpost.com/software/isell) 130 | * [Figma](https://www.figma.com/file/ZbSmB7scxfoeWxkgybsfpL/iSell?node-id=263%3A492) 131 | 132 | 133 | License 134 | ============ 135 | 136 | Copyright iSELL 2022 137 | 138 | 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: 139 | 140 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 141 | 142 | 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. 143 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | .package-lock.json 2 | package-lock.json 3 | .env 4 | build 5 | node_modules 6 | .DS_Store 7 | 8 | -------------------------------------------------------------------------------- /client/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 xyz_devs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paylancer", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@iconscout/react-unicons": "^1.1.6", 7 | "@react-hook/window-size": "^3.1.1", 8 | "@reduxjs/toolkit": "^1.8.5", 9 | "@testing-library/jest-dom": "^5.16.5", 10 | "@testing-library/react": "^13.3.0", 11 | "@testing-library/user-event": "^13.5.0", 12 | "@types/jest": "^28.1.7", 13 | "@types/node": "^18.7.11", 14 | "axios": "^0.27.2", 15 | "firebase": "9.6.6", 16 | "i18n-iso-countries": "^7.5.0", 17 | "lodash.memoize": "^4.1.2", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0", 20 | "react-redux": "^8.0.2", 21 | "react-router-dom": "^6.3.0", 22 | "react-scripts": "5.0.1", 23 | "redux": "^4.2.0", 24 | "redux-persist": "^6.0.0", 25 | "sass": "^1.54.8", 26 | "web-vitals": "^2.1.4" 27 | }, 28 | "scripts": { 29 | "start": "react-scripts start", 30 | "dev": "react-scripts start", 31 | "build": "react-scripts build", 32 | "test": "react-scripts test", 33 | "eject": "react-scripts eject" 34 | }, 35 | "eslintConfig": { 36 | "extends": [ 37 | "react-app", 38 | "react-app/jest" 39 | ] 40 | }, 41 | "browserslist": { 42 | "production": [ 43 | ">0.2%", 44 | "not dead", 45 | "not op_mini all" 46 | ], 47 | "development": [ 48 | "last 1 chrome version", 49 | "last 1 firefox version", 50 | "last 1 safari version" 51 | ] 52 | }, 53 | "devDependencies": { 54 | "@types/lodash.memoize": "^4.1.7", 55 | "typescript": "^4.7.4" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 34 | iSELL 35 | 36 | 37 | 38 |
39 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /client/public/isell-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/public/isell-1.png -------------------------------------------------------------------------------- /client/public/isell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/public/isell.png -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "iSELL", 3 | "name": "iSELL", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/src/App.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing firebase modules 5 | import { 6 | onAuthStateChangedListener, 7 | createUserDocumentFromAuth, 8 | } from "./firebase/firebase.utils"; 9 | 10 | //importing relevant modules + files 11 | import { useEffect, useState } from "react"; 12 | import { useDispatch, useSelector } from "react-redux"; 13 | import { 14 | BrowserRouter as Router, 15 | Navigate, 16 | Route, 17 | Routes, 18 | } from "react-router-dom"; 19 | import LandingPage from "./pages/landing/LandingPage"; 20 | 21 | import LoginPage from "./pages/login/LoginPage"; 22 | import SetUpPage from "./pages/setup/SetupPage"; 23 | import RegisterPage from "./pages/register/RegisterPage"; 24 | import DashboardPage from "./pages/dashboard/DashboardPage"; 25 | 26 | //importing setCurrentUser from redux reducer 27 | import { setCurrentUser } from "./store/user/user.reducer"; 28 | import Product from "./components/product/product.components"; 29 | import { RootState } from "./store/store"; 30 | import CheckOut from "./pages/check-out/check-out"; 31 | import Stores from "./pages/stores/stores"; 32 | import AlertModal from "./statics/AlertModal"; 33 | import ForgotPasswordPage from "./pages/forgot-password/ForgotPasswordPage"; 34 | import ErrorMessage from "./statics/ErrorMessage"; 35 | 36 | 37 | function App() { 38 | const getUserUid: any = useSelector( 39 | (state: RootState) => state.currentUser.currentUser 40 | ); 41 | const dispatch = useDispatch(); 42 | 43 | // setting login authentication 44 | useEffect(() => { 45 | const unsubscribe = onAuthStateChangedListener((user: Array) => { 46 | console.log(user); 47 | if (!user) return; 48 | console.log(user); 49 | 50 | if (user) { 51 | createUserDocumentFromAuth(user); 52 | } 53 | dispatch(setCurrentUser(user["uid"])); 54 | }); 55 | 56 | return unsubscribe; 57 | // eslint-disable-next-line 58 | }, []); 59 | 60 | return ( 61 | 62 | 63 | 64 | 65 | } /> 66 | } /> 67 | } /> 68 | } /> 69 | } /> 70 | } /> 71 | {getUserUid && ( 72 | } /> 73 | )} 74 | } /> 75 | } /> 76 | 77 | 78 | ); 79 | } 80 | 81 | export default App; 82 | -------------------------------------------------------------------------------- /client/src/assets/Shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/Shadow.png -------------------------------------------------------------------------------- /client/src/assets/Shape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/Shape.png -------------------------------------------------------------------------------- /client/src/assets/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/add.png -------------------------------------------------------------------------------- /client/src/assets/asian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/asian.png -------------------------------------------------------------------------------- /client/src/assets/chart1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/chart1.png -------------------------------------------------------------------------------- /client/src/assets/chart12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/chart12.png -------------------------------------------------------------------------------- /client/src/assets/check-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /client/src/assets/coil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/coil.png -------------------------------------------------------------------------------- /client/src/assets/country-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/country-icon.png -------------------------------------------------------------------------------- /client/src/assets/forgot.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/forgot.jpeg -------------------------------------------------------------------------------- /client/src/assets/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/google.png -------------------------------------------------------------------------------- /client/src/assets/isell-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/isell-logo.png -------------------------------------------------------------------------------- /client/src/assets/man.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/man.png -------------------------------------------------------------------------------- /client/src/assets/music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/music.png -------------------------------------------------------------------------------- /client/src/assets/person.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/person.jpeg -------------------------------------------------------------------------------- /client/src/assets/pfp.svg: -------------------------------------------------------------------------------- 1 | profile pic -------------------------------------------------------------------------------- /client/src/assets/product-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/product-1.png -------------------------------------------------------------------------------- /client/src/assets/product1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/product1.png -------------------------------------------------------------------------------- /client/src/assets/product2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/product2.png -------------------------------------------------------------------------------- /client/src/assets/product3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/product3.png -------------------------------------------------------------------------------- /client/src/assets/product4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/product4.png -------------------------------------------------------------------------------- /client/src/assets/product5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/product5.png -------------------------------------------------------------------------------- /client/src/assets/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/profile.png -------------------------------------------------------------------------------- /client/src/assets/profilep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/profilep.png -------------------------------------------------------------------------------- /client/src/assets/rapyd-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/rapyd-logo.png -------------------------------------------------------------------------------- /client/src/assets/setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/setup.jpg -------------------------------------------------------------------------------- /client/src/assets/shopping-cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/shopping-cart.png -------------------------------------------------------------------------------- /client/src/assets/shopping-cart.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 10 | 14 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /client/src/assets/sign-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/sign-up.png -------------------------------------------------------------------------------- /client/src/assets/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/upload.png -------------------------------------------------------------------------------- /client/src/assets/vector1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/vector1.png -------------------------------------------------------------------------------- /client/src/assets/vector2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/vector2.png -------------------------------------------------------------------------------- /client/src/assets/woman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/woman.png -------------------------------------------------------------------------------- /client/src/assets/young-picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/assets/young-picture.png -------------------------------------------------------------------------------- /client/src/components/check-out/cart-items/cart-items.scss: -------------------------------------------------------------------------------- 1 | .cart-items { 2 | display: flex; 3 | height: 21vh; 4 | @media only screen and (max-width: 768px) { 5 | height: 23vh; 6 | } 7 | @media only screen and (max-width: 1024px) { 8 | height: fit-content; 9 | } 10 | width: 90%; 11 | padding: 7px; 12 | background-color: whitesmoke; 13 | margin: auto; 14 | margin-top: 5px; 15 | margin-bottom: 5px; 16 | border-radius: 10px; 17 | .div-1 { 18 | width: 40%; 19 | .cart-image { 20 | width: 90%; 21 | border-radius: 4px; 22 | height: 21vh; 23 | } 24 | } 25 | .div-2 { 26 | width: 60%; 27 | .div-21 { 28 | .text-1 { 29 | padding-right: 10px; 30 | font-size: 15px; 31 | display: flex; 32 | align-items: center; 33 | .span-1 { 34 | font-size: 12px; 35 | flex: 1; 36 | } 37 | } 38 | .div-0 { 39 | display: flex; 40 | .div-01 { 41 | padding-left: 10px; 42 | display: flex; 43 | align-items: center; 44 | p { 45 | padding-left: 5px; 46 | padding-right: 5px; 47 | } 48 | button { 49 | margin: 3px; 50 | width: 40px; 51 | height: fit-content; 52 | cursor: pointer; 53 | } 54 | } 55 | } 56 | } 57 | .div-22 { 58 | padding-right: 5px; 59 | display: flex; 60 | justify-content: end; 61 | button { 62 | margin-right: 2px; 63 | padding: 5px; 64 | background-color: black; 65 | color: white; 66 | border-radius: 5px; 67 | cursor: pointer; 68 | text-transform: capitalize; 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /client/src/components/check-out/cart-items/cart-items.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./cart-items.scss"; 3 | import { useDispatch } from "react-redux"; 4 | import { 5 | removeItem, 6 | incrementQuantity, 7 | decrementQuantity, 8 | } from "../../../store/basket/basket"; 9 | 10 | interface Items { 11 | id: any; 12 | quantity: any; 13 | itemType: string; 14 | imageUrl: string; 15 | name: string; 16 | price: string; 17 | } 18 | const CartItems = ({ id, itemType, name, price, quantity, imageUrl }) => { 19 | const dispatch = useDispatch(); 20 | const remove = () => { 21 | dispatch(removeItem(id)); 22 | console.log("removed"); 23 | }; 24 | const increment = () => { 25 | dispatch(incrementQuantity(id)); 26 | }; 27 | const decrement = () => { 28 | dispatch(decrementQuantity(id)); 29 | }; 30 | return ( 31 |
32 |
33 | cartImage 34 |
35 |
36 |
37 |

{name}

38 |
39 |

${price}

40 |
41 | 42 |

{quantity}

43 | 44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 |
52 | ); 53 | }; 54 | 55 | export default CartItems; 56 | -------------------------------------------------------------------------------- /client/src/components/check-out/check-out.components.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import CartItems from "./cart-items/cart-items"; 3 | import "./check-out.scss"; 4 | import SubTotal from "./sub-total/sub-total"; 5 | import { useSelector } from "react-redux"; 6 | import { getTotalBasketPrice } from "../../store/basket/basket"; 7 | import { useLocation } from "react-router-dom"; 8 | 9 | const CheckOutComponent = () => { 10 | // basketTotal 11 | const cart :any = useSelector((state: any) => state.basket); 12 | const basketItems:any = cart.basket; 13 | const {state}:any = useLocation() 14 | console.log(state); 15 | 16 | return ( 17 |
18 | { 19 | basketItems.length>0 ? 20 |
21 |
22 |

Checkout

23 |
24 |

Proceed and Checkout

25 |
26 |
27 | {basketItems.map((item) => ( 28 | 37 | ))} 38 |
39 |
40 |
41 | 48 |
49 |
: 50 | window.location.pathname="/stores" 51 | } 52 | 53 |
54 | ); 55 | }; 56 | 57 | export default CheckOutComponent; 58 | -------------------------------------------------------------------------------- /client/src/components/check-out/check-out.scss: -------------------------------------------------------------------------------- 1 | .check-out { 2 | button:active, button:hover { 3 | transform: translateY(2px); 4 | } 5 | display: grid; 6 | @media only screen and (max-width: 768px) { 7 | display: flex; 8 | flex-direction: column; 9 | } 10 | grid-template-columns: repeat(5, minmax(0, 1fr)); 11 | .left-div { 12 | margin-top: 30px; 13 | grid-column: span 3 / span 3; 14 | padding: 10px; 15 | .showCart { 16 | font-size: 19px; 17 | } 18 | .div-1 { 19 | p { 20 | font-weight: 600; 21 | } 22 | } 23 | .cart { 24 | margin-top: 30px; 25 | } 26 | } 27 | .right-div { 28 | margin-top: 30px; 29 | grid-column: span 2 / span 2; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client/src/components/check-out/sub-total/sub-total.scss: -------------------------------------------------------------------------------- 1 | .sub-total { 2 | width: 80%; 3 | background-color: whitesmoke; 4 | margin: auto; 5 | margin-top: 10px; 6 | border-radius: 10px; 7 | padding: 10px; 8 | .div-1 { 9 | .text-1 { 10 | font-size: 20px; 11 | } 12 | .text-2 { 13 | display: flex; 14 | .span-1 { 15 | flex: 1; 16 | } 17 | } 18 | } 19 | button { 20 | padding: 5px; 21 | border-radius: 8px; 22 | border-color: beige; 23 | outline: none; 24 | background-color: black; 25 | cursor: pointer; 26 | color: white; 27 | text-transform: capitalize; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /client/src/components/check-out/sub-total/sub-total.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./sub-total.scss"; 3 | import {createCheckoutPage} from '../../../rapyd-hooks/create-checkout'; 4 | 5 | interface SubTypes { 6 | quantity: any; 7 | shipping: any; 8 | totalPrice: number; 9 | ewallet : string, 10 | items : Array 11 | } 12 | const SubTotal = ({ quantity, shipping, totalPrice, ewallet , items}:SubTypes) => { 13 | console.log(ewallet) 14 | 15 | const checkoutPage = async () => { 16 | const CheckOut = await createCheckoutPage( ewallet, totalPrice + shipping , items) 17 | if(CheckOut) return window.location.href = CheckOut 18 | console.log(CheckOut, 'checkout') 19 | } 20 | 21 | return ( 22 |
23 |
24 |

Order Summary

25 |

26 | Items ({quantity}) ${totalPrice} 27 |

28 |

29 | Shipping & handling ${shipping} 30 |

31 |

32 | Order total${totalPrice + shipping} 33 |

34 |
35 | 37 |
38 | ); 39 | }; 40 | 41 | export default SubTotal; 42 | -------------------------------------------------------------------------------- /client/src/components/dashboard/customer-item/customer-item.scss: -------------------------------------------------------------------------------- 1 | .div-1 { 2 | display: flex; 3 | font-size: small; 4 | color: #71717a; 5 | .customer { 6 | display: flex; 7 | width: 25%; 8 | align-items: center; 9 | .profile { 10 | width: 30px; 11 | height: 30px; 12 | margin-right: 5px; 13 | } 14 | } 15 | .email { 16 | width: 25%; 17 | display: flex; 18 | align-items: center; 19 | p { 20 | margin-left: 5px; 21 | } 22 | } 23 | .phone { 24 | width: 25%; 25 | display: flex; 26 | align-items: center; 27 | p { 28 | margin-left: 5px; 29 | } 30 | } 31 | .date { 32 | width: 25%; 33 | display: flex; 34 | align-items: center; 35 | p { 36 | margin-left: 5px; 37 | } 38 | } 39 | .country { 40 | width: 25%; 41 | display: flex; 42 | align-items: center; 43 | p { 44 | flex: 1; 45 | } 46 | .three-dots { 47 | margin-right: 10px; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /client/src/components/dashboard/customer-item/customer-item.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./customer-item.scss"; 3 | interface Customer { 4 | name: string; 5 | profile: string; 6 | email: string; 7 | contact: string; 8 | date: string; 9 | country: string; 10 | } 11 | const CustomerItem = ({ name, profile, email, contact, date, country }: Customer) => { 12 | 13 | return ( 14 |
15 |
16 | profilePic 17 |

{name}

18 |
19 |
20 |
21 | 28 | 35 | 36 |
37 |

{email}

38 |
39 |
40 |
41 | 48 | 55 | 56 |
57 |

{contact}

58 |
59 |
60 |
61 | 68 | 75 | 76 |
77 |

{date}

78 |
79 |
80 |

{country}

81 |
82 | 89 | 96 | 97 |
98 |
99 |
100 | ); 101 | }; 102 | 103 | export default CustomerItem; 104 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-create-products/dashboard-create.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //import relevant modules and file 5 | import React, { useState, useRef, useEffect } from "react"; 6 | import "./dashboard-create.scss"; 7 | import { 8 | UilShoppingBag, 9 | UilSortAmountDown, 10 | UilPricetagAlt, 11 | UilDollarAlt, 12 | UilImage, 13 | } from "@iconscout/react-unicons"; 14 | import { 15 | storage, 16 | addProductDetails, 17 | } from "../../../firebase/firebase.utils"; 18 | import { getDownloadURL, ref, uploadBytesResumable } from "firebase/storage"; 19 | import { useDispatch, useSelector } from "react-redux"; 20 | import { RootState } from "../../../store/store"; 21 | import { alert, close } from "../../../store/alert/alert.modal.reducer"; 22 | import { error,closeModal } from "../../../store/error-message/error-message.reducer"; 23 | 24 | const DashboardCreateProducts = () => { 25 | 26 | 27 | const dispatch = useDispatch(); 28 | const getUserUid: string | null = useSelector( 29 | (state: RootState) => state.currentUser.currentUser 30 | ); 31 | 32 | const [values, setValues] = useState({ 33 | product: "", 34 | stock: "default", 35 | price : "", 36 | imageLogo : "", 37 | imageUrl : "" 38 | }); 39 | 40 | // handle onChange 41 | const handleChange = (e: any) => { 42 | 43 | const { name, value } = e.target; 44 | setValues({ 45 | ...values, 46 | [name]: value, 47 | }); 48 | }; 49 | 50 | const uploadImage = async () => { 51 | try { 52 | const file = imagePicker.current.files[0]; 53 | // if (!file) return; 54 | const storageRef = ref(storage, `files/${file.name}`); 55 | const uploadTask = uploadBytesResumable(storageRef, file); 56 | 57 | uploadTask.on("state_changed", () => { 58 | getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { 59 | setValues({ 60 | ...values, 61 | imageUrl: downloadURL, 62 | }); 63 | }); 64 | }); 65 | } catch (eror) { 66 | console.log(eror); 67 | } 68 | }; 69 | 70 | const imagePicker: React.MutableRefObject = useRef(null); 71 | const { imageLogo } = values; 72 | 73 | const handleSubmit = async (e) => { 74 | 75 | e.preventDefault() 76 | if (!values.imageLogo && !values.imageUrl && !values.price && !values.product) { 77 | dispatch(error("please fill all inputs")) 78 | setTimeout(() => { 79 | dispatch(closeModal("")) 80 | }, 2000) 81 | return 82 | } 83 | 84 | 85 | try { 86 | await uploadImage(); 87 | await addProductDetails(getUserUid, values); 88 | dispatch(alert("products added ✅ ")) 89 | setTimeout(() => { 90 | dispatch(close("")) 91 | }, 2000) 92 | } 93 | catch(error) { 94 | 95 | } 96 | } 97 | 98 | useEffect(() => { 99 | uploadImage(); 100 | // eslint-disable-next-line 101 | }, [imageLogo]); 102 | 103 | // showing images 104 | const addHeaderImage = async (e: any) => { 105 | const reader = new FileReader(); 106 | if (e.target.files[0]) { 107 | reader.readAsDataURL(e.target.files[0]); 108 | } 109 | 110 | reader.onload = (readerEvent: any) => { 111 | setValues({ 112 | ...values, 113 | imageLogo: readerEvent.target.result, 114 | }); 115 | }; 116 | }; 117 | 118 | return ( 119 |
120 |

Add Product

121 |
122 |
123 | 124 | 131 |
132 |
133 | 134 | 141 | 142 |
143 |
144 | 145 | 178 |
179 | 180 |
181 |
182 | {imageLogo ? ( 183 | item 184 | ) : ( 185 | 186 | )} 187 |
188 | 195 |
imagePicker.current.click()} 198 | > 199 |

Upload Item

200 |
201 |
202 | 203 | 204 |
205 |
206 | ); 207 | }; 208 | 209 | export default DashboardCreateProducts; 210 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-create-products/dashboard-create.scss: -------------------------------------------------------------------------------- 1 | .create__products { 2 | display: flex; 3 | text-align: center; 4 | align-items: center; 5 | flex-direction: column; 6 | width: 80vw; 7 | 8 | h2 { 9 | padding-top: 20px; 10 | font-size: 19px; 11 | } 12 | .shopping { 13 | display: flex; 14 | flex-direction: row; 15 | padding-bottom: 15px; 16 | .shop { 17 | display: flex; 18 | position: absolute; 19 | margin-top: 10px; 20 | color: #A1A1AA; 21 | margin-left: 10px; 22 | width: 15px; 23 | } 24 | input { 25 | background: #FAFAFA; 26 | border: 1px solid #D4D4D8; 27 | border-radius: 5px; 28 | padding-left: 35px; 29 | width: 300px; 30 | height: 40px; 31 | outline: none; 32 | } 33 | } 34 | .price__tag { 35 | display: flex; 36 | flex-direction: row; 37 | padding-bottom: 15px; 38 | .price { 39 | display: flex; 40 | position: absolute; 41 | margin-top: 10px; 42 | color: #A1A1AA; 43 | margin-left: 10px; 44 | width: 15px; 45 | } 46 | input { 47 | background: #FAFAFA; 48 | border: 1px solid #D4D4D8; 49 | border-radius: 5px; 50 | padding-left: 35px; 51 | width: 300px; 52 | height: 40px; 53 | outline: none; 54 | -moz-appearance: textfield !important; 55 | 56 | } 57 | .dollar { 58 | cursor: pointer; 59 | position: relative; 60 | color: #A1A1AA; 61 | margin-left: -24px; 62 | margin-top: 10px; 63 | width: 20px; 64 | } 65 | 66 | } 67 | .stock__amount { 68 | display: flex; 69 | flex-direction: row; 70 | padding-bottom: 15px; 71 | .amount { 72 | display: flex; 73 | position: absolute; 74 | margin-top: 10px; 75 | color: #A1A1AA; 76 | margin-left: 10px; 77 | width: 15px; 78 | } 79 | select { 80 | background: #FAFAFA; 81 | border: 1px solid #D4D4D8; 82 | border-radius: 5px; 83 | padding-left: 32px; 84 | width: 338px; 85 | height: 40px; 86 | outline: none; 87 | -webkit-appearance: menulist-button; 88 | // color: grey; 89 | 90 | option { 91 | color: black ; 92 | } 93 | option:first-child{ 94 | color: grey; 95 | } 96 | } 97 | } 98 | .sect_img { 99 | display: flex; 100 | flex-direction: row; 101 | justify-content: space-between; 102 | padding-top: 15px; 103 | 104 | .hd_img { 105 | width: 50px; 106 | height: 50px; 107 | overflow: hidden; 108 | display: flex; 109 | font-size: 20px; 110 | justify-content: center; 111 | align-items: center; 112 | margin-right: 30px; 113 | background: whitesmoke; 114 | border: 1px solid whitesmoke; 115 | border-radius: 5px; 116 | 117 | img { 118 | width: 100%; 119 | } 120 | 121 | } 122 | .upload_add_img{ 123 | display: flex; 124 | cursor: pointer; 125 | text-transform: capitalize; 126 | background-color: whitesmoke; 127 | border: 1px solid whitesmoke; 128 | border-radius: 5px; 129 | padding: 0 10px 0 10px; 130 | 131 | 132 | } 133 | } 134 | button { 135 | display: flex; 136 | cursor: pointer; 137 | background: #18181B; 138 | width: 100%; 139 | justify-content: center; 140 | padding: 7px; 141 | border-radius: 10px; 142 | font-weight: bold; 143 | outline: none; 144 | color: #fff; 145 | -webkit-appearance: button; 146 | border: none; 147 | margin-top: 17px; 148 | height: 40px; 149 | align-items: center; 150 | align-content: center; 151 | } 152 | } -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-customers/dashboard-customers.scss: -------------------------------------------------------------------------------- 1 | .dashboard-customers { 2 | padding: 30px; 3 | width: 100%; 4 | color: #71717a; 5 | .head-div { 6 | width: 100%; 7 | height: 13vh; 8 | display: flex; 9 | justify-content: baseline; 10 | padding: 2px; 11 | .div-1 { 12 | .title { 13 | font-family: "Plus Jakarta Sans"; 14 | font-style: normal; 15 | font-weight: 700; 16 | font-size: 21px; 17 | /* identical to box height, or 152% */ 18 | 19 | /* gray/900 */ 20 | 21 | color: #18181b; 22 | } 23 | .description { 24 | font-family: "Plus Jakarta Sans"; 25 | font-style: normal; 26 | font-weight: 400; 27 | font-size: 13px; 28 | line-height: 22px; 29 | /* identical to box height, or 169% */ 30 | 31 | /* gray/500 */ 32 | 33 | color: #71717a; 34 | } 35 | flex: 1; 36 | display: flex; 37 | flex-direction: column; 38 | align-self: end; 39 | } 40 | .div-2 { 41 | display: flex; 42 | align-items: end; 43 | .container-1 { 44 | border: 1px solid; 45 | cursor: pointer; 46 | padding-left: 5px; 47 | padding-right: 5px; 48 | margin-right: 5px; 49 | border-radius: 8px; 50 | display: flex; 51 | font-size: small; 52 | .svg-export { 53 | font-size: 10px; 54 | margin-right: 4px; 55 | } 56 | } 57 | .container-2 { 58 | border: 1px solid; 59 | cursor: pointer; 60 | padding-left: 5px; 61 | padding-right: 5px; 62 | border-radius: 8px; 63 | .text-sort { 64 | font-size: small; 65 | margin-right: 4px; 66 | } 67 | .svg-sort { 68 | font-size: 12px; 69 | } 70 | display: flex; 71 | font-size: small; 72 | margin-left: 5px; 73 | align-items: end; 74 | } 75 | } 76 | } 77 | .div-type { 78 | border: 1px solid; 79 | display: flex; 80 | margin-top: 10px; 81 | border-top: none; 82 | border-left: none; 83 | padding: 10px; 84 | border-right: none; 85 | border-color: rgba($color: #000000, $alpha: 0.2); 86 | .customer { 87 | width: 25%; 88 | } 89 | .email { 90 | width: 25%; 91 | } 92 | .phone { 93 | width: 25%; 94 | } 95 | .date { 96 | width: 25%; 97 | } 98 | .country { 99 | width: 25%; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-customers/dashboard-customers.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CustomerItem from "../customer-item/customer-item"; 3 | import "./dashboard-customers.scss"; 4 | const DashboardCustomers = () => { 5 | const profilePic = require("../../../assets/profile.png"); 6 | return ( 7 |
8 |
9 |
10 |

Customers

11 |

12 | Lorem ipsum dolor sit amet, consectetur adipis. 13 |

14 |
15 |
16 |
17 |

18 | 25 | 32 | 33 |

34 |

Export to CSV

35 |
36 |
37 |

Sort: Popularity

38 |

39 | 46 | 53 | 54 |

55 |
56 |
57 |
58 |
59 |
60 |

Customer

61 |
62 |
63 |

Email Address

64 |
65 |
66 |

Phone Number

67 |
68 |
69 |

Join Date

70 |
71 |
72 |

Country

73 |
74 |
75 | 83 |
84 | ); 85 | }; 86 | 87 | export default DashboardCustomers; 88 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-navbar/dashboard-navbar.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //import relevant modules 5 | 6 | import React, { useState } from "react"; 7 | import './dashboard-navbar.scss'; 8 | import { useWindowSize } from "@react-hook/window-size"; 9 | import MobileMenu from "./mobile-menu/mobile-menu"; 10 | 11 | 12 | // import logo 13 | const isellLogo : string = require('../../../assets/isell-logo.png'); 14 | const person : string = require('../../../assets/person.jpeg'); 15 | 16 | const DashboardNavbar = ({businessDetails, displayName}) => { 17 | const [menubar, setmenuBar] = useState(false) 18 | 19 | const [width] = useWindowSize(); 20 | return ( 21 |
22 |
23 | 24 | isell logo 25 |
26 | 27 |
28 | {/* { 29 | width <= 768 && 30 |
31 |
{setmenuBar(!menubar); console.log(menubar)}} 33 | style={{ 34 | zIndex: menubar ? "1200" : "0" 35 | }} 36 | > 37 | 58 |
59 | { 60 | !menubar ? : null 61 | } 62 | 63 |
64 | } */} 65 | { 66 | businessDetails && person pfp 67 | } 68 | 69 |

{displayName}

70 |
71 |
72 | 73 | ); 74 | } 75 | 76 | export default DashboardNavbar; 77 | 78 | 79 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-navbar/dashboard-navbar.scss: -------------------------------------------------------------------------------- 1 | .dashboard__navbar { 2 | // display: flex; 3 | // justify-content: space-between; 4 | // flex-direction: row; 5 | box-shadow: 0px 1px 0px rgba(18, 32, 59, 0.09); 6 | border-bottom: 1px solid #e4e4e7; 7 | 8 | display: grid; 9 | overflow-y: scroll; 10 | position: sticky; 11 | top: 0; 12 | grid-template-columns: repeat(5, minmax(0, 1fr)); 13 | z-index: 10; 14 | 15 | .dashboard__sidebar { 16 | display: block; 17 | overflow: hidden; 18 | padding-left: 20px; 19 | grid-column: span 1 / span 1; 20 | position: sticky; 21 | // display: flex; 22 | // flex-direction: column; 23 | border-right: 1px solid #e4e4e7; 24 | 25 | padding-right: 130px; 26 | @media screen and (max-width: 768px) { 27 | border: none; 28 | } 29 | .dashboard__logo { 30 | padding: 20px 0px 20px 0px; 31 | width: 50px; 32 | height: 20px; 33 | // padding-right: 20px; 34 | } 35 | .sidebar { 36 | display: flex; 37 | flex-direction: column; 38 | } 39 | } 40 | 41 | .navbar__content { 42 | display: flex; 43 | flex-direction: row; 44 | margin-bottom: 4px; 45 | padding-top: 20px; 46 | padding-right: 20px; 47 | justify-self: flex-end; 48 | grid-column: span 4 / span 4; 49 | position: sticky; 50 | 51 | .menu-bars { 52 | // position: fixed; 53 | // top: 1rem; 54 | // right: 2rem; 55 | // z-index: 10; 56 | // display: inline; 57 | margin-top: 2px; 58 | /* margin-left: 20px; */ 59 | background: whitesmoke; 60 | border: solid 1px grey; 61 | border-radius : 5px; 62 | margin-right: 6px; 63 | cursor: pointer; 64 | } 65 | 66 | .bar1, 67 | .bar2, 68 | .bar3 { 69 | width: 21px; 70 | height: 2px; 71 | background-color: black; 72 | margin: 5px 5px 5px 6px; 73 | transition: 0.4s; 74 | } 75 | 76 | /* Rotate first bar */ 77 | .change .bar1 { 78 | transform: rotate(-45deg) translate(-6px, 5px); 79 | } 80 | 81 | /* Fade out the second bar */ 82 | .change .bar2 { 83 | opacity: 0; 84 | } 85 | 86 | /* Rotate last bar */ 87 | .change .bar3 { 88 | transform: rotate(45deg) translate(-5px, -4px); 89 | } 90 | 91 | .person__logo { 92 | height: 30px; 93 | width: 30px; 94 | border-radius: 100%; 95 | padding: 0 10px 0 10px; 96 | } 97 | .person__p { 98 | margin-top: 5px; 99 | font-size: 13px; 100 | padding: 0 10px 0 10px; 101 | } 102 | .angle__down { 103 | margin: 5px 0px 0px 0px; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-navbar/mobile-menu/mobile-menu.scss: -------------------------------------------------------------------------------- 1 | .desk__menubar{ 2 | z-index: 1; 3 | position: fixed; 4 | top: 0; 5 | bottom: 0; 6 | left: 0; 7 | right: 0; 8 | background-color: rgba(0,0,0,0.2); 9 | opacity: 1; 10 | transition: opacity .2s ease-in-out; 11 | cursor: auto; 12 | 13 | .desk__menuitem{ 14 | position: absolute; 15 | background-color: var(--on-settings-card); 16 | flex-direction: column; 17 | display: flex; 18 | border: solid 1px var(--on-settings-card); 19 | border-radius: 10px; 20 | width: 190px; 21 | // height: 100px; 22 | top: 64px; 23 | right: 232px; 24 | color: var(--wht); 25 | 26 | ul { 27 | display: flex; 28 | flex-direction: column; 29 | text-align: left; 30 | 31 | .desk { 32 | margin-left: 10px !important; 33 | margin: 10px; 34 | cursor: pointer; 35 | font-weight: bold; 36 | 37 | &:hover { 38 | // margin-left: -14px !important; 39 | border-right: solid 5px #3981C6 !important; 40 | background-color: var(--background--hover); 41 | color: #3981C6; 42 | } 43 | 44 | // &:hover{ 45 | // .uil-arrow-up-right{ 46 | // transition: 0.2s; 47 | // transform: translateX(10px); 48 | // } 49 | 50 | // } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-navbar/mobile-menu/mobile-menu.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import './mobile-menu.scss'; 3 | 4 | const MobileMenu = () => { 5 | return( 6 |
7 |
8 |
    9 |
  • 10 | 11 | Github 12 |
  • 13 |
  • 14 | Twitter 15 | 16 |
  • 17 | 18 |
19 |
20 | 21 |
22 | ) 23 | } 24 | 25 | export default MobileMenu 26 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-products/dashboard-products.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //import relevant modules 5 | import React, { useEffect, useState } from "react"; 6 | import { useNavigate } from "react-router-dom"; 7 | import './dashboard-products.scss'; 8 | import {UilPlus} from '@iconscout/react-unicons'; 9 | import { useSelector } from "react-redux"; 10 | import { RootState } from "../../../store/store"; 11 | import { db } from "../../../firebase/firebase.utils"; 12 | import memoize from 'lodash.memoize'; 13 | import { doc, getDoc } from "firebase/firestore"; 14 | import Spinner from "../../spinner/spinner"; 15 | import { Link } from "react-router-dom"; 16 | 17 | //import logo 18 | const uploadImg = require('../../../assets/upload.png'); 19 | 20 | //JSX Components 21 | const DashboardProducts = () => { 22 | const Navigate = useNavigate(); 23 | 24 | const getUserUid: any = useSelector( 25 | (state: RootState) => state.currentUser.currentUser 26 | ); 27 | const [products, setProducts]:any = useState([]); 28 | const [loading, setloading] = useState(false); 29 | const [name, setName] = useState("") 30 | 31 | const getVendorProducts = memoize(async () => { 32 | setloading(false); 33 | if(!getUserUid) { 34 | return Navigate('/login') 35 | } 36 | const getDocRef = doc(db, "users", getUserUid); 37 | if (!getDocRef) return 38 | const userSnapshot= await getDoc(getDocRef); 39 | if (userSnapshot?.data()?.verification) { 40 | setProducts(userSnapshot.data()?.products) 41 | setName(userSnapshot.data()?.businessDetails?.business_name) 42 | setloading(true); 43 | } 44 | 45 | }) 46 | 47 | 48 | useEffect(() => { 49 | getVendorProducts() 50 | // eslint-disable-next-line 51 | }, [getUserUid]) 52 | return( 53 |
54 | { 55 | !loading ? 56 | 57 | : 58 | products.length> 0 && loading ? 59 | 60 |
61 |
62 |
63 |

Products

64 |

Store owned by {name}

65 |
66 | 67 | 68 | 69 | 70 |
71 | 72 |
73 | 74 | { 75 | products.map((product, i) => 76 | ( 77 |
78 |
79 |

{product?.stock}

80 | 81 |
82 |
83 |

{product?.product}

84 |

{product?.price}

85 |
86 |
87 | )) 88 | } 89 |
90 |
91 | 92 | : 93 |
94 | upload icon 95 |

Start by uploading a product

96 |

Any product you upload on iSELL will live here.

97 |

Start creating your Products.

98 | 99 | 105 | 106 |
107 | } 108 | 109 | 110 | 111 |
112 | ); 113 | } 114 | 115 | export default DashboardProducts; 116 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-products/dashboard-products.scss: -------------------------------------------------------------------------------- 1 | .dashboard__upload { 2 | display: flex; 3 | flex-direction: column; 4 | grid-column: span 4 / span 4; 5 | width: 80vw; 6 | @media only screen and (max-width: 768px) { 7 | width: 100vw; 8 | } 9 | 10 | .vendor__products { 11 | display: flex; 12 | flex-direction: column; 13 | .add__products { 14 | display: flex; 15 | flex-direction: row; 16 | justify-content: space-between; 17 | .btn-add { 18 | padding-right: 20px; 19 | } 20 | .products__main { 21 | h2 { 22 | padding: 20px 0px 0px 30px; 23 | font-size: 18px; 24 | } 25 | p { 26 | font-size: 12px; 27 | margin: -10px 0px 0px 30px; 28 | color: #71717a; 29 | } 30 | } 31 | button { 32 | margin: 20px 5px 0px 5px; 33 | display: flex; 34 | cursor: pointer; 35 | background: #18181b; 36 | justify-content: center; 37 | padding: 5px; 38 | border-radius: 10px; 39 | font-weight: bold; 40 | outline: none; 41 | color: #fff; 42 | width: 100px; 43 | -webkit-appearance: button; 44 | border: none; 45 | margin-top: 30px; 46 | height: 40px; 47 | align-items: center; 48 | align-content: center; 49 | } 50 | } 51 | 52 | .products { 53 | display: grid; 54 | // grid-template-columns: 1fr 1fr 1fr 1fr; 55 | // grid-gap: 10px; 56 | 57 | // padding: 80px 10px 0px 10px; 58 | grid-template-columns: repeat(9, minmax(0, 1fr)); 59 | width: 80vw; 60 | @media only screen and (max-width: 768px) { 61 | width: 100vw; 62 | grid-template-columns: repeat(8, minmax(0, 1fr)); 63 | } 64 | 65 | .dash-pro { 66 | grid-column: span 3 / span 3; 67 | @media only screen and (max-width: 768px) { 68 | grid-column: span 4 / span 4; 69 | } 70 | 71 | .product { 72 | margin: 10px; 73 | background: whitesmoke; 74 | border: solid 1px whitesmoke; 75 | border-radius: 10px; 76 | display: flex; 77 | flex-direction: column; 78 | // justify-content: center; 79 | // align-content: center; 80 | // text-align: center; 81 | width: 20vw; 82 | @media only screen and (max-width: 768px) { 83 | width: fit-content; 84 | height: 250px; 85 | } 86 | height: 300px; 87 | 88 | & p { 89 | display: flex; 90 | text-align: center; 91 | justify-content: center; 92 | margin-top: 8px; 93 | background-color: #18181b; 94 | color: white; 95 | margin-left: 10px; 96 | width: 24px; 97 | border: solid 1px #18181b; 98 | border-radius: 10px; 99 | height: 18px; 100 | font-size: 12px; 101 | } 102 | img { 103 | display: flex; 104 | justify-content: center; 105 | margin: 10px 0px 0px 29px; 106 | height: 70%; 107 | width: 80%; 108 | border-radius: 5%; 109 | background-image: none !important; 110 | } 111 | } 112 | .product__details { 113 | width: 20vw; 114 | margin-top: 10px 10px 5px 10px; 115 | display: flex; 116 | justify-content: space-between; 117 | flex-direction: row; 118 | 119 | h2 { 120 | padding: 0px; 121 | font-size: 11px; 122 | 123 | margin: 0px; 124 | margin-left: 13px; 125 | // font-weight: bolder; 126 | } 127 | p { 128 | margin-top: 0px; 129 | font-size: 13px; 130 | } 131 | } 132 | } 133 | } 134 | } 135 | 136 | .dashboard-products { 137 | display: flex; 138 | padding-top: 100px; 139 | flex-direction: column; 140 | width: 80vw; 141 | text-align: center; 142 | justify-content: center; 143 | align-content: center; 144 | align-items: center; 145 | 146 | & img { 147 | width: 132px; 148 | height: 98px; 149 | } 150 | & h2 { 151 | font-size: 16px; 152 | margin-bottom: 1px; 153 | } 154 | & p { 155 | font-size: 14px; 156 | line-height: 20px; 157 | color: #667085; 158 | margin: auto; 159 | } 160 | & button { 161 | margin: 0px 5px 0px 5px; 162 | display: flex; 163 | cursor: pointer; 164 | background: #18181b; 165 | justify-content: center; 166 | padding: 5px; 167 | border-radius: 10px; 168 | font-weight: bold; 169 | outline: none; 170 | color: #fff; 171 | width: 20%; 172 | -webkit-appearance: button; 173 | border: none; 174 | margin-top: 17px; 175 | height: 40px; 176 | align-items: center; 177 | align-content: center; 178 | span { 179 | margin-top: -1px; 180 | text-transform: capitalize; 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-sales/dashboard-sales.component.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const DashboardSales = () => { 4 | return ( 5 |

Sales

6 | ); 7 | } 8 | 9 | export default DashboardSales; -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-sidebar/dashboard-sidebar.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //import relevant modules 5 | import React from "react"; 6 | import { Link } from "react-router-dom"; 7 | import { 8 | UilPlus, 9 | UilEstate, 10 | UilSignalAlt3, 11 | UilUserArrows, 12 | UilFolder, 13 | UilSignout, 14 | } from "@iconscout/react-unicons"; 15 | import "./dashboard-sidebar.scss"; 16 | 17 | //JSX Component 18 | const DashboardSidebar = () => { 19 | return ( 20 |
21 |
22 | 23 | 27 | 28 |
29 |
30 | 31 | 32 | 33 |

Dashboard

34 | 35 | 36 |
37 |
38 |

Analytics

39 |
40 | 41 |

Sales

42 |
43 |
44 |
45 |

Support

46 |
47 | 48 |

Customers

49 |
50 |
51 |
52 |

Shop

53 |
54 | 55 | 56 | 57 |

Products

58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 | 66 |

Logout

67 |
68 |
69 | ); 70 | }; 71 | 72 | export default DashboardSidebar; 73 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard-sidebar/dashboard-sidebar.scss: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | 3 | display: block; 4 | overflow: hidden; 5 | grid-column: span 1 / span 1; 6 | position: sticky; 7 | @media only screen and (max-width: 768px) { 8 | display: none; 9 | } 10 | height: 90vh; 11 | top: 0px; 12 | bottom: 0px; 13 | 14 | .sidebar__component1 { 15 | padding-top: 10px; 16 | 17 | .product__button { 18 | margin: 0px 5px 0px 5px; 19 | display: flex; 20 | cursor: pointer; 21 | background: #18181b; 22 | justify-content: center; 23 | padding: 5px; 24 | border-radius: 10px; 25 | font-weight: bold; 26 | outline: none; 27 | color: #fff; 28 | width: 90%; 29 | -webkit-appearance: button; 30 | border: none; 31 | margin-top: 17px; 32 | height: 40px; 33 | align-items: center; 34 | align-content: center; 35 | span { 36 | margin-top: -1px; 37 | text-transform: capitalize; 38 | } 39 | } 40 | 41 | .sidebarsub__component { 42 | display: flex; 43 | flex-direction: column; 44 | padding: 20px 9px 10px 16px; 45 | width: 200px; 46 | .home__dashboard { 47 | display: flex; 48 | flex-direction: row; 49 | justify-content: space-between; 50 | width: 50%; 51 | cursor: pointer; 52 | .home__dash { 53 | // margin-top: 5px; 54 | width: 18px; 55 | color: #18181b; 56 | } 57 | .dashboard__paragraph { 58 | font-size: 14px; 59 | margin-top: 3px; 60 | color: #18181b; 61 | } 62 | } 63 | .analytics__dashboard { 64 | display: flex; 65 | width: 50%; 66 | flex-direction: column; 67 | 68 | .analytics { 69 | font-size: 11px; 70 | letter-spacing: 1px; 71 | font-weight: 500; 72 | text-transform: uppercase; 73 | color: #a1a1aa; 74 | padding-left: 5px; 75 | } 76 | 77 | .signals__dashboard { 78 | display: flex; 79 | flex-direction: row; 80 | justify-content: space-between; 81 | width: 65%; 82 | // padding: 10px 5px 10px 5px; 83 | cursor: pointer; 84 | 85 | .signal { 86 | width: 16px; 87 | // margin-right: 10px; 88 | } 89 | .sales { 90 | font-size: 14px; 91 | margin-top: 3px; 92 | } 93 | } 94 | } 95 | .support__dashboard { 96 | display: flex; 97 | width: 50%; 98 | flex-direction: column; 99 | .support { 100 | font-size: 11px; 101 | letter-spacing: 1px; 102 | font-weight: 500; 103 | text-transform: uppercase; 104 | color: #a1a1aa; 105 | padding-left: 5px; 106 | } 107 | .customers__dashboard { 108 | display: flex; 109 | flex-direction: row; 110 | justify-content: space-between; 111 | cursor: pointer; 112 | 113 | .customers { 114 | width: 16px; 115 | } 116 | .customer { 117 | font-size: 14px; 118 | margin-top: 3px; 119 | } 120 | } 121 | } 122 | .shop__dashboard { 123 | display: flex; 124 | width: 50%; 125 | flex-direction: column; 126 | & p { 127 | font-size: 11px; 128 | letter-spacing: 1px; 129 | font-weight: 500; 130 | text-transform: uppercase; 131 | color: #a1a1aa; 132 | padding-left: 5px; 133 | } 134 | & div { 135 | display: flex; 136 | flex-direction: row; 137 | justify-content: space-between; 138 | cursor: pointer; 139 | .products { 140 | width: 16px; 141 | } 142 | & p { 143 | color: black; 144 | text-transform: capitalize; 145 | font-size: 14px; 146 | margin-top: 3px; 147 | } 148 | } 149 | } 150 | } 151 | } 152 | .sidebar__component2 { 153 | margin-left: 15px; 154 | margin-top: 180px; 155 | display: flex; 156 | width: 39%; 157 | flex-direction: row; 158 | justify-content: space-between; 159 | cursor: pointer; 160 | .logout { 161 | width: 16px; 162 | margin-left: 3px; 163 | } 164 | & p { 165 | color: black; 166 | text-transform: capitalize; 167 | font-size: 14px; 168 | margin-top: 3px; 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //import relevant modules and file 5 | import React, { useEffect, useState } from "react"; 6 | import { doc, getDoc } from "firebase/firestore"; 7 | 8 | import memoize from 'lodash.memoize'; 9 | import { useSelector } from "react-redux"; 10 | import "./dashboard.scss"; 11 | 12 | //import sections of the dashboard 13 | import DashboardNavbar from "./dashboard-navbar/dashboard-navbar.component"; 14 | import DashboardSidebar from "./dashboard-sidebar/dashboard-sidebar.component"; 15 | import DashboardProducts from "./dashboard-products/dashboard-products.component"; 16 | import DashboardSales from "./dashboard-sales/dashboard-sales.component"; 17 | import DashboardCreateProducts from "./dashboard-create-products/dashboard-create.component"; 18 | import { Route, Routes } from "react-router-dom"; 19 | import { RootState } from "../../store/store"; 20 | import { db } from "../../firebase/firebase.utils"; 21 | // import DashboardCustomers from "./dashboard-customers/dashboard-customers"; 22 | 23 | const Dashboard = () => { 24 | 25 | const getUserUid: any = useSelector( 26 | (state: RootState) => state.currentUser.currentUser 27 | ); 28 | 29 | const [loading, setLoading] = useState(false); 30 | const [verified, setVerification]= useState(false); 31 | const [details, setDetails]:any = useState([]); 32 | 33 | const detailedObject= memoize(async () => { 34 | setLoading(false); 35 | if(!getUserUid) return 36 | const getDocRef = doc(db, "users", getUserUid); 37 | if (!getDocRef) return 38 | const userSnapshot:any = await getDoc(getDocRef); 39 | if (userSnapshot?.data()?.verification) { 40 | setDetails(userSnapshot?.data()) 41 | setVerification(userSnapshot.data()?.verification) 42 | setLoading(true); 43 | } 44 | 45 | }) 46 | 47 | useEffect(() => { 48 | detailedObject(); 49 | // eslint-disable-next-line 50 | }, [getUserUid]) 51 | return ( 52 | 53 |
54 | 55 |
56 | 57 | 58 | } /> 59 | } /> 60 | } /> 61 | {/* } /> */} 62 | 63 |
64 |
65 | ); 66 | }; 67 | 68 | export default Dashboard; 69 | -------------------------------------------------------------------------------- /client/src/components/dashboard/dashboard.scss: -------------------------------------------------------------------------------- 1 | .dashboard { 2 | display: flex; 3 | flex-direction: column; 4 | background-color: #fff; 5 | 6 | .dashboard__main { 7 | // display: flex; 8 | // flex-direction: row;; 9 | display: grid; 10 | overflow-y: scroll; 11 | position: sticky; 12 | overflow-x: hidden; 13 | top: 0; 14 | height: 100vh; 15 | grid-template-columns: repeat(5, minmax(0, 1fr)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client/src/components/forgot-password/forgot-password.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // relevant firebase imports 5 | import React, { useState } from "react"; 6 | import './forgot.scss'; 7 | import {UilEnvelope} from '@iconscout/react-unicons' 8 | import { Link } from "react-router-dom"; 9 | import { resetPassword } from "../../firebase/firebase.utils"; 10 | import { error, closeModal} from "../../store/error-message/error-message.reducer"; 11 | import { alert , close} from "../../store/alert/alert.modal.reducer"; 12 | import { useDispatch } from "react-redux"; 13 | 14 | const ForgotPassword = () => { 15 | const dispatch = useDispatch() 16 | const [email, setEmail] = useState(""); 17 | const isellLogo= require('../../assets/isell-logo.png'); 18 | 19 | const handleSubmit = async (e: React.FormEvent) => { 20 | e.preventDefault() 21 | !email && dispatch(error("Enter Email Address")) 22 | setTimeout(() => { 23 | dispatch(closeModal("")) 24 | }, 2000) 25 | try { 26 | await resetPassword(email) 27 | 28 | } 29 | catch(err :any) { 30 | if(err.code === 'auth/network-request-failed') { 31 | dispatch(error("A network error, try again later")) 32 | setTimeout(() => { 33 | dispatch(closeModal("")) 34 | }, 2000) 35 | } else { 36 | dispatch(error(`user not found`)) 37 | setTimeout(() => { 38 | dispatch(closeModal("")) 39 | }, 2000) 40 | } 41 | console.log(err) 42 | } 43 | setEmail("") 44 | } 45 | 46 | return ( 47 |
48 |
49 | 50 | isell logo 51 | 52 | 53 |
54 |

Reset Password

55 |
56 |
57 | 58 | {setEmail(e.target.value)}} 60 | name="email" 61 | value={email} 62 | type='text' 63 | placeholder="Email address"/> 64 |
65 | 66 | 69 | 70 |
71 | 72 |
73 |
74 |
75 |
76 |
77 |
78 | ); 79 | } 80 | 81 | export default ForgotPassword; -------------------------------------------------------------------------------- /client/src/components/forgot-password/forgot.scss: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | .login { 5 | display: flex; 6 | background-color: #ffff; 7 | flex-direction: row; 8 | justify-content: space-between; 9 | 10 | @media screen and (max-width: 1000px) { 11 | text-align: center; 12 | justify-content: center; 13 | } 14 | 15 | .login__component1 { 16 | display: flex; 17 | flex-direction: column; 18 | padding: 50px; 19 | 20 | @media screen and (max-width: 1000px) { 21 | padding-left: 0px; 22 | padding-right: 0px; 23 | 24 | } 25 | img { 26 | width : 50px; 27 | padding: 20px; 28 | cursor: pointer; 29 | 30 | @media screen and (max-width: 1000px) { 31 | padding: 0px; 32 | position: absolute; 33 | left: 30px; 34 | } 35 | } 36 | .log__body { 37 | padding-top: 75px; 38 | display: flex; 39 | flex-direction: column; 40 | 41 | .email__address { 42 | display: flex; 43 | flex-direction: row; 44 | 45 | 46 | .envelope{ 47 | display: flex; 48 | position: absolute; 49 | margin-top: 10px; 50 | color: #A1A1AA; 51 | margin-left: 10px; 52 | width: 15px; 53 | } 54 | input { 55 | background: #FAFAFA; 56 | border: 1px solid #D4D4D8; 57 | border-radius: 5px; 58 | padding-left: 35px; 59 | width: 300px; 60 | height: 40px; 61 | outline: none; 62 | } 63 | 64 | } 65 | 66 | button { 67 | display: flex; 68 | cursor: pointer; 69 | background: #18181B; 70 | width: 100%; 71 | justify-content: center; 72 | padding: 7px; 73 | border-radius: 10px; 74 | font-weight: bold; 75 | outline: none; 76 | color: #fff; 77 | -webkit-appearance: button; 78 | border: none; 79 | margin-top: 17px; 80 | height: 40px; 81 | align-items: center; 82 | align-content: center; 83 | } 84 | 85 | } 86 | } 87 | .forgot__component2 { 88 | position: relative; 89 | border-radius: 10px; 90 | display: flex; 91 | width: 50vw; 92 | height: 100vh; 93 | background: url('../../assets/forgot.jpeg'); 94 | background-repeat: no-repeat; 95 | background-size: cover; 96 | @media screen and (max-width : 1000px) { 97 | display: none; 98 | } 99 | // .forgot__layer{ 100 | // background: linear-gradient(90deg, #44BCFF -0.55%, #44B0FF 22.86%, #FF44EC 48.36%, #FF44EC 73.33%, #FF675E 99.34%); 101 | // opacity: 0.9; 102 | // filter: blur(70.333px); 103 | // transform: matrix(1, 0, 0, 1, 0, 0); 104 | // position: absolute; 105 | // height: 208.42px; 106 | // left: 0px; 107 | // top: 490.97px; 108 | // width: 50vw; 109 | // } 110 | 111 | } 112 | } -------------------------------------------------------------------------------- /client/src/components/home/footer/footer.components.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./footer.scss"; 3 | const Footer = () => { 4 | const iSELLlogo = require("../../../assets/isell-logo.png"); 5 | return ( 6 |
7 |

8 | Online sales made easy

with the best tools 9 |

10 |
11 | 12 |
13 |
14 | isell 15 |

16 | iSELL gives you the building blocks to build a truly profitable 17 | business. 18 |

19 |
20 |

21 | © Copyright 2022, All Rights Reserved by iSELL 22 |

23 |
24 | ); 25 | }; 26 | 27 | export default Footer; 28 | -------------------------------------------------------------------------------- /client/src/components/home/footer/footer.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | width: 100%; 3 | height: 100vh; 4 | display: flex; 5 | @media only screen and (max-width: 768px) { 6 | flex-direction: column; 7 | } 8 | @media only screen and (max-width: 915px) { 9 | height: fit-content; 10 | flex-direction: column; 11 | margin-top: 10vh; 12 | } 13 | .title { 14 | font-family: "Plus Jakarta Sans"; 15 | font-style: normal; 16 | font-weight: 600; 17 | font-size: 52px; 18 | line-height: 56px; 19 | /* or 108% */ 20 | 21 | text-align: center; 22 | } 23 | .div-1 { 24 | width: 100%; 25 | display: flex; 26 | justify-content: center; 27 | button { 28 | background: #18181b; 29 | color: white; 30 | padding: 11px; 31 | border-radius: 3px; 32 | } 33 | } 34 | .div-2 { 35 | margin-top: 20vh; 36 | width: 100%; 37 | padding-top: 40px; 38 | padding-bottom: 40px; 39 | border: solid; 40 | border-color: rgba(0, 0, 0, 0.3); 41 | border-width: 1px; 42 | border-left: none; 43 | border-right: none; 44 | display: flex; 45 | align-items: center; 46 | .isell { 47 | width: 50px; 48 | height: 20px; 49 | } 50 | .isell-text { 51 | flex: 1; 52 | text-align: end; 53 | } 54 | } 55 | .copyright { 56 | text-align: center; 57 | margin-top: 15vh; 58 | margin-bottom: 10vh; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /client/src/components/home/hero-section/hero-section.components.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./hero-section.scss"; 3 | const HeroSection = () => { 4 | const image1 = require("../../../assets/chart1.png"); 5 | const image2 = require("../../../assets/chart12.png"); 6 | const image3 = require("../../../assets/music.png"); 7 | return ( 8 |
9 |

What makes us special

10 |

Why should you conduct your business on iSell

11 |
12 |
13 | icon 14 |

Support

15 |

16 | We offer 24/7 Support to our Vendors. If you run into any issues 17 | with payment or customer orders, we’re only a chat away. 18 |

19 |
20 |
21 | icon 22 |

Sales

23 |

24 | We provides the structure you need for you to grow your business 25 | sales, making you a more profitable vendor. 26 |

27 |
28 |
29 | icon 30 |

Easy Onboarding

31 |

32 | It’s very easy to gets started as a vendor on iSELL, Create a free 33 | account to get started 34 |

35 |
36 |
37 |
38 | 39 |
40 |
41 | ); 42 | }; 43 | 44 | export default HeroSection; 45 | -------------------------------------------------------------------------------- /client/src/components/home/hero-section/hero-section.scss: -------------------------------------------------------------------------------- 1 | .hero-section { 2 | width: 90%; 3 | margin: auto; 4 | height: 100vh; 5 | @media only screen and (max-width: 918px) { 6 | height: fit-content; 7 | } 8 | .text-1 { 9 | height: 56px; 10 | @media only screen and (max-width: 768px) { 11 | font-weight: 600; 12 | font-size: 29px; 13 | } 14 | font-family: "Plus Jakarta Sans"; 15 | font-style: normal; 16 | font-weight: 600; 17 | font-size: 45px; 18 | /* identical to box height, or 124% */ 19 | 20 | text-align: center; 21 | 22 | /* Base/02 */ 23 | 24 | color: #090914; 25 | } 26 | .text-2 { 27 | margin-top: -30px; 28 | text-align: center; 29 | @media only screen and (max-width: 768px) { 30 | margin-bottom: 6vh; 31 | } 32 | } 33 | .hero-0 { 34 | @media only screen and (max-width: 768px) { 35 | flex-wrap: wrap; 36 | height: fit-content; 37 | } 38 | @media only screen and (max-width: 918px) { 39 | height: fit-content; 40 | } 41 | display: flex; 42 | height: 40vh; 43 | padding: 50px; 44 | justify-content: space-around; 45 | align-items: center; 46 | .hero-1 { 47 | display: flex; 48 | flex-direction: column; 49 | align-items: center; 50 | width: 330px; 51 | margin: 10px; 52 | .hero-header { 53 | font-size: 18px; 54 | font-weight: 500; 55 | } 56 | .hero-description { 57 | width: 80%; 58 | font-size: 14px; 59 | } 60 | } 61 | .hero-2 { 62 | display: flex; 63 | flex-direction: column; 64 | align-items: center; 65 | width: 380px; 66 | margin: 10px; 67 | border-style: solid; 68 | border-width: 1px; 69 | border-top: none; 70 | border-bottom: none; 71 | border-color: rgba(0, 0, 0, 0.3); 72 | .hero-header { 73 | font-size: 18px; 74 | font-weight: 500; 75 | } 76 | .hero-description { 77 | width: 80%; 78 | font-size: 14px; 79 | } 80 | } 81 | .hero-3 { 82 | display: flex; 83 | flex-direction: column; 84 | align-items: center; 85 | width: 330px; 86 | margin: 10px; 87 | .hero-header { 88 | font-size: 18px; 89 | font-weight: 500; 90 | } 91 | .hero-description { 92 | width: 80%; 93 | font-size: 14px; 94 | } 95 | } 96 | } 97 | .btn-div { 98 | width: 100%; 99 | display: flex; 100 | justify-content: center; 101 | button { 102 | background: #18181b; 103 | color: white; 104 | padding: 8px; 105 | border-radius: 3px; 106 | 107 | @media only screen and (max-width: 768px) { 108 | margin-bottom: 6vh; 109 | } 110 | 111 | @media only screen and (max-width: 918px) { 112 | margin-bottom: 9vh; 113 | } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /client/src/components/home/home.component.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Footer from "./footer/footer.components"; 3 | import HeroSection from "./hero-section/hero-section.components"; 4 | import "./home.scss"; 5 | 6 | //import sections of the landing page 7 | import Navbar from "./navbar/navbar.component"; 8 | import SplashSection from "./splash-section/splash-section.component"; 9 | import SubFooter from "./sub-footer/sub-footer.component"; 10 | import SubSection from "./sub-section/sub-section.component"; 11 | 12 | const Home = () => { 13 | return ( 14 |
15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | ); 23 | }; 24 | 25 | export default Home; 26 | -------------------------------------------------------------------------------- /client/src/components/home/home.scss: -------------------------------------------------------------------------------- 1 | .homepage { 2 | button { 3 | text-transform: capitalize; 4 | cursor: pointer; 5 | border-radius: 10px !important; 6 | } 7 | background-color: #ffffff; 8 | display: flex; 9 | flex-direction: column; 10 | margin: 0 20px 0 20px; 11 | 12 | .navbar { 13 | padding-left: 30px; 14 | display: flex; 15 | justify-content: space-between; 16 | @media only screen and (max-width: 285px) { 17 | align-items: center; 18 | } 19 | border-bottom: solid 1px #a1a1aa; 20 | padding: 0 10px 0px 10px; 21 | img { 22 | width: 60px; 23 | height: 29px; 24 | margin-top: 10px; 25 | @media only screen and (max-width: 285px) { 26 | width: 40px; 27 | margin-right: 10px; 28 | height: 20px; 29 | flex: 1; 30 | } 31 | } 32 | .sign_in_and_login { 33 | display: flex; 34 | flex-direction: row; 35 | 36 | p { 37 | padding: 0 10px 0 5px; 38 | @media only screen and (max-width: 285px) { 39 | padding: 0px; 40 | width: 70px; 41 | } 42 | } 43 | button:last-child { 44 | cursor: pointer; 45 | background-color: #18181b; 46 | color: #ffffff; 47 | // padding: 5px; 48 | margin: 5px; 49 | @media only screen and (max-width: 285px) { 50 | font-size: 10px; 51 | } 52 | border-radius: 10px; 53 | } 54 | } 55 | } 56 | .splash { 57 | padding-top: 30px; 58 | display: flex; 59 | flex-direction: row; 60 | padding-left: 20px; 61 | 62 | // justify-content: space-between; 63 | 64 | .component__one { 65 | @media only screen and (max-width: 768px) { 66 | width: 100%; 67 | } 68 | width: 50vw; 69 | display: flex; 70 | flex-direction: column; 71 | .wave__component { 72 | width: 250px; 73 | @media only screen and (max-width: 285px) { 74 | width: 200px; 75 | top: 300px; 76 | padding: 5px; 77 | font-size: 13px; 78 | } 79 | padding: 10px; 80 | border-radius: 10px; 81 | color: #ffffff; 82 | background: linear-gradient( 83 | 90deg, 84 | #44bcff -0.55%, 85 | #44b0ff 22.86%, 86 | #ff44ec 48.36%, 87 | #ff44ec 73.33%, 88 | #ff675e 99.34% 89 | ); 90 | .wave { 91 | animation-name: wave-animation; /* Refers to the name of your @keyframes element below */ 92 | animation-duration: 2.5s; /* Change to speed up or slow down */ 93 | animation-iteration-count: infinite; /* Never stop waving :) */ 94 | transform-origin: 70% 70%; /* Pivot around the bottom-left palm */ 95 | display: inline-block; 96 | 97 | @keyframes wave-animation { 98 | 0% { 99 | transform: rotate(0deg); 100 | } 101 | 10% { 102 | transform: rotate(14deg); 103 | } /* The following five values can be played with to make the waving more or less extreme */ 104 | 20% { 105 | transform: rotate(-8deg); 106 | } 107 | 30% { 108 | transform: rotate(14deg); 109 | } 110 | 40% { 111 | transform: rotate(-4deg); 112 | } 113 | 50% { 114 | transform: rotate(10deg); 115 | } 116 | 60% { 117 | transform: rotate(0deg); 118 | } /* Reset for the last half to pause */ 119 | 100% { 120 | transform: rotate(0deg); 121 | } 122 | } 123 | } 124 | } 125 | h2 { 126 | @media only screen and (max-width: 768px) { 127 | // line-height: 36px; 128 | margin-top: 10px; 129 | font-weight: 500; 130 | font-size: 35px; 131 | } 132 | @media only screen and (max-width: 285px) { 133 | // line-height: 22px; 134 | margin-top: 10px; 135 | font-weight: 500; 136 | font-size: 25px; 137 | } 138 | // line-height: 66px; 139 | margin-top: 10px; 140 | font-weight: 700; 141 | } 142 | button { 143 | margin-top: 20px; 144 | display: flex; 145 | cursor: pointer; 146 | padding: 10px; 147 | width: 10vw; 148 | text-transform: capitalize; 149 | text-align: center; 150 | justify-content: center; 151 | background-color: #18181b; 152 | font-size: 12px; 153 | color: white; 154 | @media only screen and (max-width: 768px) { 155 | width: fit-content; 156 | } 157 | @media only screen and (max-width: 285px) { 158 | font-size: 12px; 159 | } 160 | } 161 | .sponsor { 162 | display: flex; 163 | margin-top: 50px; 164 | 165 | p { 166 | padding: 30px; 167 | @media only screen and (max-width: 285px) { 168 | padding: 15px; 169 | } 170 | } 171 | img { 172 | width: 100px; 173 | height: 30px; 174 | padding-top: 43px; 175 | } 176 | } 177 | } 178 | .component__two { 179 | display: flex; 180 | flex-direction: column; 181 | width: 50vw; 182 | @media only screen and (max-width: 768px) { 183 | width: 100%; 184 | margin-bottom: 16vh; 185 | } 186 | margin-left: 20px; 187 | .coil { 188 | width: 150px; 189 | } 190 | .AA { 191 | @media only screen and (max-width: 768px) { 192 | width: 90%; 193 | margin-left: 10px; 194 | } 195 | width: 35vw; 196 | border-radius: 10px; 197 | margin-left: 74px; 198 | margin-top: -67px; 199 | } 200 | .products { 201 | z-index: 1; 202 | position: absolute; 203 | display: flex; 204 | flex-direction: row; 205 | .product-1 { 206 | @media only screen and (max-width: 768px) { 207 | width: 120px; 208 | top: 200px; 209 | left: -30px; 210 | } 211 | @media only screen and (max-width: 285px) { 212 | width: 80px; 213 | top: 120px; 214 | left: -40px; 215 | } 216 | @media only screen and (max-width: 920px) { 217 | top: 180px; 218 | left: 10px; 219 | } 220 | @media only screen and (max-width: 1024px) { 221 | top: 240px; 222 | left: 10px; 223 | } 224 | @media only screen and (max-width: 415px) { 225 | top: 180px; 226 | left: -40px; 227 | } 228 | position: relative; 229 | margin-left: 10px; 230 | top: 350px; 231 | display: flex; 232 | flex-direction: column; 233 | padding: 10px; 234 | width: 150px; 235 | border-radius: 10px; 236 | background-color: #ffffff; 237 | box-shadow: 193px 193px 109px rgba(0, 0, 0, 0.01), 238 | 109px 109px 92px rgba(0, 0, 0, 0.05), 239 | 48px 48px 68px rgba(0, 0, 0, 0.09), 240 | 12px 12px 38px rgba(0, 0, 0, 0.1), 0px 0px 0px rgba(0, 0, 0, 0.1); 241 | .product__subsection { 242 | display: flex; 243 | flex-direction: row; 244 | justify-content: space-between; 245 | padding: 5px; 246 | 247 | img { 248 | border: solid 1px #d0d5dd; 249 | width: 20px; 250 | height: 20px; 251 | padding: 10px; 252 | border-radius: 5px; 253 | } 254 | button { 255 | color: #ffffff; 256 | text-transform: capitalize; 257 | background-color: #18181b; 258 | @media only screen and (max-width: 768px) { 259 | padding: 0px; 260 | font-size: 12px; 261 | padding-left: 3px; 262 | padding-right: 3px; 263 | } 264 | border-radius: 5px; 265 | cursor: pointer; 266 | padding: 5px; 267 | // margin: 0 15px 0 15px; 268 | } 269 | } 270 | } 271 | } 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /client/src/components/home/navbar/navbar.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant files and modules 5 | import React from "react"; 6 | // import styles 7 | import "./navbar.scss"; 8 | import { useSelector } from "react-redux"; 9 | import { Link, useNavigate } from "react-router-dom"; 10 | 11 | // import logo 12 | const cartImage = require("../../../assets/Shape.png"); 13 | const iSELLlogo = require("../../../assets/isell-logo.png"); 14 | const shoppingLogo = require("../../../assets/shopping-cart.png") 15 | 16 | interface Active { 17 | isActive: boolean; 18 | } 19 | // JSX component 20 | const Navbar = (props) => { 21 | const cart = useSelector((state: any) => state.basket); 22 | const Navigate = useNavigate(); 23 | console.log(props.state, 'props') 24 | 25 | const getVendorWallet = () => { 26 | Navigate('/checkout', {state: props.state}) 27 | } 28 | 29 | return ( 30 |
31 | 34 | isell logo 35 | 36 | 37 |
38 | 39 |

Sign in

40 | 41 | 42 | 43 | 44 | 45 |
46 | cart 47 |

{cart.basket?.length}

48 |
49 |
50 |
51 | ); 52 | }; 53 | 54 | export default Navbar; 55 | -------------------------------------------------------------------------------- /client/src/components/home/navbar/navbar.scss: -------------------------------------------------------------------------------- 1 | .navbar { 2 | padding-left: 30px; 3 | display: flex; 4 | justify-content: space-between; 5 | border-bottom: solid 1px #a1a1aa; 6 | padding: 0 10px 0px 10px; 7 | img { 8 | width: 60px; 9 | height: 29px; 10 | margin-top: 10px; 11 | } 12 | .sign_in_and_login { 13 | display: flex; 14 | flex-direction: row; 15 | 16 | p { 17 | cursor: pointer; 18 | padding: 0 10px 0 5px; 19 | } 20 | .navbar-btn { 21 | cursor: pointer; 22 | background-color: #18181b; 23 | color: #ffffff; 24 | padding: 10px; 25 | // padding: 5px; 26 | margin: 5px; 27 | text-transform: capitalize; 28 | border-radius: 10px; 29 | } 30 | .navbar-cart { 31 | display: flex; 32 | border-radius: 100%; 33 | padding-left: 10px; 34 | padding-right: 10px; 35 | .cart { 36 | width: 30px; 37 | height: 30px; 38 | } 39 | .count { 40 | font-size: 13px; 41 | margin-top: 19px; 42 | margin-left: -25px; 43 | text-align: center; 44 | } 45 | } 46 | .navbar-nocart { 47 | display: none; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /client/src/components/home/splash-section/splash-section.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant files and modules 5 | import React from "react"; 6 | 7 | // styles 8 | import "./splash-section.scss"; 9 | 10 | // import logos 11 | const rapydLogo = require("../../../assets/rapyd-logo.png"); 12 | const product1 = require("../../../assets/product-1.png"); 13 | const product2 = require("../../../assets/product2.png"); 14 | const cartLogo = require("../../../assets/Shape.png"); 15 | const coilLogo = require("../../../assets/coil.png"); 16 | const youngAAIMG = require("../../../assets/young-picture.png"); 17 | 18 | //JSX component; 19 | const SplashSection = () => { 20 | return ( 21 |
22 |
23 |

24 | {" "} 25 | Hello there 👋🏽, Welcome to isell 26 |

27 |

The easiest way to sell and earn online

28 |

33 | {" "} 34 | iSELL leverages on the world’s fastest and most secure payment portal 35 | to give you the best seling experience you can get. 36 |

37 | 38 |
39 |

Secure Payment by

40 | rapyd logo 41 |
42 |
43 |
44 | coil logo 45 | young AA 46 |
47 |
48 | product-1 49 |
50 | cart logo 51 | 54 |
55 |
56 |
57 | product-2 58 |
59 | cart logo 60 | 63 |
64 |
65 |
66 |
67 |
68 | ); 69 | }; 70 | 71 | export default SplashSection; 72 | -------------------------------------------------------------------------------- /client/src/components/home/splash-section/splash-section.scss: -------------------------------------------------------------------------------- 1 | .splash { 2 | padding-top: 30px; 3 | display: flex; 4 | flex-direction: row; 5 | padding-left: 20px; 6 | @media only screen and (max-width: 768px) { 7 | flex-wrap: wrap; 8 | } 9 | 10 | // justify-content: space-between; 11 | 12 | .component__one { 13 | @media only screen and (max-width: 768px) { 14 | width: 100%; 15 | } 16 | width: 50vw; 17 | display: flex; 18 | flex-direction: column; 19 | .wave__component { 20 | @media only screen and (max-width: 285px) { 21 | width: 100px; 22 | } 23 | width: 250px; 24 | padding: 10px; 25 | border-radius: 10px; 26 | color: #ffffff; 27 | background: linear-gradient( 28 | 90deg, 29 | #44bcff -0.55%, 30 | #44b0ff 22.86%, 31 | #ff44ec 48.36%, 32 | #ff44ec 73.33%, 33 | #ff675e 99.34% 34 | ); 35 | .wave { 36 | animation-name: wave-animation; /* Refers to the name of your @keyframes element below */ 37 | animation-duration: 2.5s; /* Change to speed up or slow down */ 38 | animation-iteration-count: infinite; /* Never stop waving :) */ 39 | transform-origin: 70% 70%; /* Pivot around the bottom-left palm */ 40 | display: inline-block; 41 | 42 | @keyframes wave-animation { 43 | 0% { 44 | transform: rotate(0deg); 45 | } 46 | 10% { 47 | transform: rotate(14deg); 48 | } /* The following five values can be played with to make the waving more or less extreme */ 49 | 20% { 50 | transform: rotate(-8deg); 51 | } 52 | 30% { 53 | transform: rotate(14deg); 54 | } 55 | 40% { 56 | transform: rotate(-4deg); 57 | } 58 | 50% { 59 | transform: rotate(10deg); 60 | } 61 | 60% { 62 | transform: rotate(0deg); 63 | } /* Reset for the last half to pause */ 64 | 100% { 65 | transform: rotate(0deg); 66 | } 67 | } 68 | } 69 | } 70 | h2 { 71 | // line-height: 66px; 72 | margin-top: 10px; 73 | font-weight: 700; 74 | } 75 | button { 76 | margin-top: 20px; 77 | display: flex; 78 | cursor: pointer; 79 | padding: 10px; 80 | width: 10vw; 81 | border-radius: 10px; 82 | } 83 | .sponsor { 84 | display: flex; 85 | margin-top: 50px; 86 | p { 87 | padding: 30px; 88 | } 89 | img { 90 | width: 100px; 91 | height: 30px; 92 | padding-top: 43px; 93 | } 94 | } 95 | } 96 | .component__two { 97 | display: flex; 98 | flex-direction: column; 99 | width: 50vw; 100 | margin-left: 20px; 101 | @media only screen and (max-width: 768px) { 102 | width: 100%; 103 | } 104 | .coil { 105 | width: 150px; 106 | } 107 | .AA { 108 | width: 35vw; 109 | border-radius: 10px; 110 | margin-left: 74px; 111 | margin-top: -67px; 112 | } 113 | .products { 114 | z-index: 1; 115 | position: absolute; 116 | display: flex; 117 | flex-direction: row; 118 | .product-1 { 119 | position: relative; 120 | margin-left: 10px; 121 | top: 350px; 122 | display: flex; 123 | flex-direction: column; 124 | padding: 10px; 125 | width: 150px; 126 | border-radius: 10px; 127 | background-color: #ffffff; 128 | box-shadow: 193px 193px 109px rgba(0, 0, 0, 0.01), 129 | 109px 109px 92px rgba(0, 0, 0, 0.05), 130 | 48px 48px 68px rgba(0, 0, 0, 0.09), 12px 12px 38px rgba(0, 0, 0, 0.1), 131 | 0px 0px 0px rgba(0, 0, 0, 0.1); 132 | .product__subsection { 133 | display: flex; 134 | flex-direction: row; 135 | justify-content: space-between; 136 | padding: 5px; 137 | 138 | img { 139 | border: solid 1px #d0d5dd; 140 | width: 20px; 141 | height: 20px; 142 | padding: 10px; 143 | border-radius: 5px; 144 | } 145 | button { 146 | color: #ffffff; 147 | 148 | border-radius: 5px; 149 | cursor: pointer; 150 | padding: 5px; 151 | @media only screen and (max-width: 768px) { 152 | padding: 0px; 153 | } 154 | // margin: 0 15px 0 15px; 155 | } 156 | } 157 | } 158 | .product-2 { 159 | position: relative; 160 | margin-left: 10px; 161 | top: 520px; 162 | left: 280px; 163 | display: flex; 164 | @media only screen and (max-width: 768px) { 165 | width: 120px; 166 | top: 300px; 167 | left: 30px; 168 | } 169 | @media only screen and (max-width: 360px) { 170 | width: 120px; 171 | top: 300px; 172 | left: 10px; 173 | } 174 | @media only screen and (max-width: 920px) { 175 | top: 270px; 176 | left: 60px; 177 | } 178 | @media only screen and (max-width: 1024px) { 179 | top: 320px; 180 | left: 120px; 181 | } 182 | @media only screen and (max-width: 415px) { 183 | top: 290px; 184 | left: 40px; 185 | } 186 | @media only screen and (max-width: 285px) { 187 | width: 80px; 188 | top: 200px; 189 | left: -10px; 190 | } 191 | @media only screen and (max-width: 915px) { 192 | top: 290px; 193 | left: 22px; 194 | } 195 | flex-direction: column; 196 | padding: 10px; 197 | width: 150px; 198 | border-radius: 10px; 199 | background-color: #ffffff; 200 | box-shadow: 193px 193px 109px rgba(0, 0, 0, 0.01), 201 | 109px 109px 92px rgba(0, 0, 0, 0.05), 202 | 48px 48px 68px rgba(0, 0, 0, 0.09), 12px 12px 38px rgba(0, 0, 0, 0.1), 203 | 0px 0px 0px rgba(0, 0, 0, 0.1); 204 | .product__subsection { 205 | display: flex; 206 | flex-direction: row; 207 | justify-content: space-between; 208 | padding: 5px; 209 | 210 | img { 211 | border: solid 1px #d0d5dd; 212 | width: 20px; 213 | height: 20px; 214 | padding: 10px; 215 | border-radius: 5px; 216 | } 217 | button { 218 | background: #18181b;; 219 | color: #ffffff; 220 | @media only screen and (max-width: 768px) { 221 | padding: 0px; 222 | font-size: 12px; 223 | padding-left: 3px; 224 | padding-right: 3px; 225 | } 226 | border-radius: 5px; 227 | cursor: pointer; 228 | padding: 5px; 229 | // margin: 0 15px 0 15px; 230 | } 231 | } 232 | } 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /client/src/components/home/sub-footer/sub-footer.component.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./sub-footer.scss"; 3 | const SubFooter = () => { 4 | const woman = require("../../../assets/woman.png"); 5 | const shadow = require("../../../assets/Shadow.png"); 6 | return ( 7 |
8 |
9 |
10 | shadow 11 |
12 | woman 13 |
14 |

How it works

15 |

16 | It's very easy to create a store on iSell. Get started today 17 |

18 |
19 |
20 |

1

21 |

22 | Sign up and create your first online store with ease. 23 |

24 |
25 |
26 |

2

27 |

28 | Add your products to your store and their details. 29 |

30 |
31 |
32 |

3

33 |

34 | Get realtime updates of your customer's activities. 35 |

36 |
37 |
38 |

4

39 |

40 | Sell and earn as much as you can. Grow your business fast. 41 |

42 |
43 |
44 |
45 |
46 | ); 47 | }; 48 | 49 | export default SubFooter; 50 | -------------------------------------------------------------------------------- /client/src/components/home/sub-footer/sub-footer.scss: -------------------------------------------------------------------------------- 1 | .sub-footer { 2 | width: 100%; 3 | height: 100vh; 4 | display: flex; 5 | @media only screen and (max-width: 918px) { 6 | height: fit-content; 7 | margin-top: 10vh; 8 | } 9 | @media only screen and (max-width: 768px) { 10 | height: fit-content; 11 | margin-bottom: 7vh; 12 | } 13 | align-items: center; 14 | .mat { 15 | box-sizing: border-box; 16 | 17 | position: absolute; 18 | width: 339.05px; 19 | height: 349.25px; 20 | left: -121.66px; 21 | z-index: 1; 22 | opacity: 0.2; 23 | border-radius: 50%; 24 | /* blue-gray/100 */ 25 | 26 | border: 7px solid #0071e1; 27 | transform: matrix(0.92, -0.77, 0.29, 0.83, 0, 0); 28 | } 29 | .woman { 30 | height: 70vh; 31 | position: absolute; 32 | margin-left: 280px; 33 | @media only screen and (max-width: 768px) { 34 | display: none; 35 | } 36 | @media only screen and (max-width: 918px) { 37 | height: 45vh; 38 | margin-left: 30px; 39 | } 40 | } 41 | .backg { 42 | height: 450px; 43 | width: 90%; 44 | margin-left: 60px; 45 | @media only screen and (max-width: 918px) { 46 | height: 40vh; 47 | } 48 | @media only screen and (max-width: 768px) { 49 | margin-left: 10px; 50 | height: 70vh; 51 | margin-bottom: 10vh; 52 | } 53 | margin-top: 75px; 54 | position: absolute; 55 | border-radius: 20px; 56 | background: #18181b; 57 | .shadow { 58 | width: 100%; 59 | margin-top: -58px; 60 | @media only screen and (max-width: 768px) { 61 | margin-top: 64.5vh; 62 | margin-bottom: 5vh; 63 | } 64 | 65 | @media only screen and (max-width: 918px) { 66 | margin-top: 18vh; 67 | margin-bottom: 5vh; 68 | } 69 | } 70 | } 71 | .sub-footer-1 { 72 | width: 60%; 73 | @media only screen and (max-width: 768px) { 74 | width: 100%; 75 | padding: 10%; 76 | } 77 | z-index: 1; 78 | margin-left: auto; 79 | display: flex; 80 | flex-wrap: wrap; 81 | flex-direction: column; 82 | align-items: center; 83 | .text-1 { 84 | margin-top: 50px; 85 | font-family: "Plus Jakarta Sans"; 86 | font-style: normal; 87 | font-weight: 600; 88 | font-size: 40px; 89 | 90 | /* identical to box height, or 124% */ 91 | 92 | text-align: center; 93 | color: #ffffff; 94 | } 95 | .text-2 { 96 | position: absolute; 97 | width: 485px; 98 | height: 56px; 99 | margin-top: 100px; 100 | font-family: "Inter"; 101 | font-style: normal; 102 | font-weight: 400; 103 | font-size: 18px; 104 | line-height: 28px; 105 | @media only screen and (max-width: 768px) { 106 | width: fit-content; 107 | flex-wrap: wrap; 108 | padding-left: 40px; 109 | padding-right: 40px; 110 | } 111 | /* or 156% */ 112 | 113 | text-align: center; 114 | color: white; 115 | mix-blend-mode: normal; 116 | } 117 | .sub-footer-2 { 118 | width: 80%; 119 | @media only screen and (max-width: 768px) { 120 | width: 100%; 121 | margin-top: 7vh; 122 | padding: 0px; 123 | } 124 | display: flex; 125 | flex-wrap: wrap; 126 | padding: 30px; 127 | 128 | .sub-footer1 { 129 | width: 39%; 130 | margin-right: 30px; 131 | background-color: white; 132 | border-radius: 14px; 133 | display: flex; 134 | align-items: center; 135 | padding-left: 8px; 136 | @media only screen and (max-width: 768px) { 137 | width: 100%; 138 | margin-bottom: 10px; 139 | margin-right: 0px; 140 | } 141 | .text1 { 142 | padding: 10px; 143 | font-weight: 700; 144 | border-radius: 5px; 145 | margin-right: 10px; 146 | background-color: black; 147 | color: white; 148 | } 149 | .text11 { 150 | flex: 1; 151 | } 152 | } 153 | .sub-footer2 { 154 | @media only screen and (max-width: 768px) { 155 | width: 100%; 156 | margin-bottom: 10px; 157 | margin-right: 0px; 158 | } 159 | width: 39%; 160 | background-color: white; 161 | border-radius: 14px; 162 | display: flex; 163 | align-items: center; 164 | padding: 8px; 165 | 166 | .text2 { 167 | padding: 10px; 168 | font-weight: 700; 169 | border-radius: 5px; 170 | margin-right: 10px; 171 | background-color: black; 172 | color: white; 173 | } 174 | .text12 { 175 | flex: 1; 176 | } 177 | } 178 | .sub-footer3 { 179 | @media only screen and (max-width: 768px) { 180 | width: 100%; 181 | margin-bottom: 10px; 182 | margin-right: 0px; 183 | margin-top: 0px; 184 | } 185 | width: 38%; 186 | background-color: white; 187 | border-radius: 14px; 188 | display: flex; 189 | align-items: center; 190 | padding: 8px; 191 | margin-top: 20px; 192 | margin-right: 30px; 193 | .text3 { 194 | padding: 10px; 195 | font-weight: 700; 196 | border-radius: 5px; 197 | margin-right: 10px; 198 | background-color: black; 199 | color: white; 200 | } 201 | .text13 { 202 | flex: 1; 203 | } 204 | } 205 | .sub-footer4 { 206 | @media only screen and (max-width: 768px) { 207 | width: 100%; 208 | width: 100%; 209 | margin-bottom: 10px; 210 | margin-right: 0px; 211 | margin-top: 0px; 212 | } 213 | width: 39%; 214 | background-color: white; 215 | border-radius: 14px; 216 | display: flex; 217 | align-items: center; 218 | padding: 10px; 219 | margin-top: 20px; 220 | .text4 { 221 | padding: 10px; 222 | font-weight: 700; 223 | border-radius: 5px; 224 | margin-right: 10px; 225 | background-color: black; 226 | color: white; 227 | } 228 | .text14 { 229 | flex: 1; 230 | } 231 | } 232 | } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /client/src/components/home/sub-section/sub-section.component.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./sub-section.scss"; 3 | 4 | const SubSection = () => { 5 | const profile = require("../../../assets/profile.png"); 6 | const man = require("../../../assets/man.png"); 7 | const vector1 = require("../../../assets/vector1.png"); 8 | const vector2 = require("../../../assets/vector2.png"); 9 | return ( 10 |
11 |
12 | man 13 |
14 |
15 | profile 16 |
17 |

Product Manager

18 |

Albert Flores

19 |
20 |
21 |
22 |

Customer ID

23 |

Last Active

24 |

Provided task

25 |
26 |
27 |
28 |

Improve your sales

29 |
30 |

31 | Online sales made
easy with better tools. 32 |

33 |

34 |
35 |
36 |
37 | 44 | 51 | 52 |

Get unlimited products uploads. Level up your sales.

53 |
54 |
55 | 62 | 69 | 70 |

Collect payments manage your customers and many more.

71 |
72 |
73 | 74 |
75 | vector1 76 | vector2 77 |
78 | ); 79 | }; 80 | 81 | export default SubSection; 82 | -------------------------------------------------------------------------------- /client/src/components/home/sub-section/sub-section.scss: -------------------------------------------------------------------------------- 1 | .sub-section { 2 | height: 100vh; 3 | width: 100%; 4 | display: flex; 5 | align-items: center; 6 | @media only screen and (max-width: 768px) { 7 | flex-direction: column-reverse; 8 | padding: 20px; 9 | } 10 | @media only screen and (max-width: 918px) { 11 | width: 100%; 12 | height: fit-content; 13 | margin-top: 40px; 14 | padding: 20px; 15 | } 16 | .vector1 { 17 | position: absolute; 18 | right: 1px; 19 | margin-top: 150px; 20 | opacity: 0.1; 21 | width: 200px; 22 | } 23 | .vector2 { 24 | width: 170px; 25 | position: absolute; 26 | right: 10px; 27 | margin-top: -120px; 28 | opacity: 0.1; 29 | } 30 | .left-div { 31 | width: 50%; 32 | display: flex; 33 | justify-content: center; 34 | align-items: center; 35 | @media only screen and (max-width: 768px) { 36 | width: 100%; 37 | padding: 20px; 38 | margin-bottom: 7vh; 39 | } 40 | img { 41 | border-radius: 10px; 42 | width: 80%; 43 | } 44 | .details { 45 | position: absolute; 46 | width: 336.68px; 47 | height: 191px; 48 | margin-top: 220px; 49 | margin-left: 120px; 50 | /* Base/02 */ 51 | @media only screen and (max-width: 768px) { 52 | margin-left: 20px; 53 | } 54 | @media only screen and (max-width: 918px) { 55 | margin-left: 20px; 56 | width: 236.68px; 57 | height: 181px; 58 | } 59 | background: #090914; 60 | box-shadow: 0px 30px 57px rgba(10, 7, 37, 0.14), 61 | 0px 4px 4px rgba(0, 0, 0, 0.03); 62 | border-radius: 10px; 63 | .first-details { 64 | color: white; 65 | display: flex; 66 | .profile-img { 67 | width: 40px; 68 | padding: 5px; 69 | height: 40px; 70 | } 71 | .text-2 { 72 | padding: 5px; 73 | padding-left: 20px; 74 | .manager-text { 75 | color: gray; 76 | } 77 | p { 78 | display: table-footer-group; 79 | } 80 | } 81 | } 82 | hr { 83 | margin-left: 10px; 84 | margin-right: 10px; 85 | } 86 | p { 87 | color: rgba(255, 252, 252, 0.875); 88 | padding-left: 10px; 89 | } 90 | } 91 | } 92 | .right-div { 93 | width: 50%; 94 | @media only screen and (max-width: 768px) { 95 | width: 100%; 96 | margin-bottom: 5vh; 97 | } 98 | @media only screen and (max-width: 918px) { 99 | margin-right: 20px; 100 | } 101 | .text-1 { 102 | color: #ff44ec; 103 | } 104 | .description { 105 | font-family: "Plus Jakarta Sans"; 106 | font-style: normal; 107 | font-weight: 600; 108 | font-size: 45px; 109 | line-height: 56px; 110 | @media only screen and (max-width: 768px) { 111 | font-weight: 600; 112 | font-size: 35px; 113 | line-height: 46px; 114 | } 115 | /* or 124% */ 116 | 117 | /* Base/02 */ 118 | 119 | color: #090914; 120 | } 121 | .features { 122 | width: 100%; 123 | display: flex; 124 | div { 125 | width: 230px; 126 | padding: 10px; 127 | display: flex; 128 | margin-bottom: 20px; 129 | svg { 130 | padding: 4px; 131 | margin-top: 15px; 132 | } 133 | p { 134 | flex: 1; 135 | } 136 | } 137 | } 138 | button { 139 | background-color: #18181b; 140 | color: white; 141 | padding: 8px; 142 | border-radius: 3px; 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /client/src/components/login/login.component.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // relevant firebase imports 5 | import { 6 | signInWithGooglePopup, 7 | createUserDocumentFromAuth, 8 | checkverification, 9 | signInAuthUserWithEmailAndPassword 10 | } from "../../firebase/firebase.utils"; 11 | 12 | //importing relevant modules 13 | 14 | import { useDispatch } from "react-redux"; 15 | import React, { useEffect, useState } from "react"; 16 | import validateInfo from "../../validation/validation2"; 17 | import { Link } from "react-router-dom"; 18 | import { setCurrentUser } from "../../store/user/user.reducer"; 19 | import { UilEnvelope, 20 | UilLock , UilEye, UilEyeSlash } from '@iconscout/react-unicons' 21 | import { error ,closeModal} from "../../store/error-message/error-message.reducer"; 22 | 23 | //importing styles 24 | import "./login.scss"; 25 | 26 | 27 | //importing relevant assets 28 | const googleLogo = require("../../assets/google.png"); 29 | const backgroundImage = require('../../assets/young-picture.png'); 30 | const isellLogo = require('../../assets/isell-logo.png'); 31 | 32 | 33 | 34 | //JSX login 35 | const Login = () => { 36 | const dispatch = useDispatch() 37 | 38 | //sign in with google 39 | const signInWithGoogle = async () => { 40 | const { user } = await signInWithGooglePopup(); 41 | await createUserDocumentFromAuth(user); 42 | const verified = await checkverification(user.uid); 43 | dispatch(setCurrentUser(user.uid)) 44 | if(verified) { 45 | 46 | return window.location.pathname = '/dashboard' 47 | } 48 | return window.location.pathname = '/setup' 49 | }; 50 | 51 | // values of email and password initial state 52 | const [values, setValues] = useState({ 53 | email: "", 54 | password: "", 55 | loginType : false 56 | }); 57 | 58 | // getting the values 59 | const {email, password} = values 60 | ; 61 | // set initial error state and if there is submission 62 | const [errors, setErrors] = useState({}); 63 | const [isSubmitting, setIsSubmitting] = useState(false); 64 | 65 | // handle onChange 66 | const handleChange = (e: React.ChangeEvent) => { 67 | const { name, value } = e.target; 68 | setValues({ 69 | ...values, 70 | [name]: value, 71 | }); 72 | }; 73 | 74 | // handle on submit 75 | const handleSubmit = async (e: React.FormEvent) => { 76 | e.preventDefault(); 77 | setErrors(validateInfo(values)); 78 | setIsSubmitting(true); 79 | 80 | if(!email && !password) { 81 | dispatch(error('Fill all inputs')); 82 | setTimeout(() => { 83 | dispatch(closeModal("")) 84 | }, 2000); 85 | return 86 | } 87 | 88 | try { 89 | const {user} :any["user"] = await signInAuthUserWithEmailAndPassword( 90 | email, 91 | password 92 | ); 93 | if(!user) return 94 | const verified = await checkverification(user.uid); 95 | setCurrentUser(user.uid); 96 | 97 | if(verified) { 98 | setValues({ 99 | ...values, 100 | email: "", 101 | password: "", 102 | loginType : false 103 | }) 104 | return window.location.pathname = '/dashboard' 105 | } 106 | setValues({ 107 | ...values, 108 | email: "", 109 | password: "", 110 | loginType : false 111 | }) 112 | return window.location.pathname = '/setup' 113 | 114 | } 115 | catch(err : any) { 116 | switch (err.code) { 117 | case 'auth/wrong-password': 118 | dispatch(error('incorrect password for email')); 119 | setTimeout(() => { 120 | dispatch(closeModal("")) 121 | }, 2000); 122 | break; 123 | case 'auth/user-not-found': 124 | dispatch(error('no user associated with this email')); 125 | setTimeout(() => { 126 | dispatch(closeModal("")) 127 | }, 2000); 128 | break; 129 | case "auth/network-request-failed" : 130 | dispatch(error('network error, try again later')); 131 | setTimeout(() => { 132 | dispatch(closeModal("")) 133 | }, 2000); 134 | break; 135 | case "auth/too-many-requests" : 136 | dispatch(error('too many requests, try again later')); 137 | setTimeout(() => { 138 | dispatch(closeModal("")) 139 | }, 2000); 140 | break; 141 | default: 142 | console.log(err); 143 | } 144 | } 145 | }; 146 | 147 | useEffect(() => { 148 | if (Object.keys(errors).length === 0 && isSubmitting) { 149 | // if no error is found 150 | console.log(values); 151 | } 152 | // eslint-disable-next-line 153 | }, [errors]); 154 | return ( 155 |
156 |
157 | isell logo 158 |
159 |

Welcome back to iSELL

160 |
161 |
162 | 163 | 169 |
170 |
171 | 172 | 178 | { 179 | values.loginType ? 180 | { setValues({ 181 | ...values, 182 | loginType: !values.loginType, 183 | })}} /> 184 | : 185 | { setValues({ 186 | ...values, 187 | loginType: !values.loginType, 188 | })}} /> 189 | } 190 | 191 |
192 |
193 |
194 | 195 |

Remember me

196 |
197 | 198 |

Forgot Password?

199 | 200 | 201 |
202 | 205 | 206 |
207 |
208 |

or

209 | 213 |
214 |

Don't have an account? 215 | 220 | Sign up now 221 |

222 |
223 |
224 |
225 |
226 |
227 |
228 | ); 229 | }; 230 | 231 | export default Login; 232 | -------------------------------------------------------------------------------- /client/src/components/login/login.scss: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | .login { 5 | display: flex; 6 | background-color: #ffff; 7 | flex-direction: row; 8 | justify-content: space-between; 9 | 10 | @media screen and (max-width: 1000px) { 11 | text-align: center; 12 | justify-content: center; 13 | } 14 | 15 | .login__component1 { 16 | display: flex; 17 | flex-direction: column; 18 | padding: 50px; 19 | 20 | @media screen and (max-width: 1000px) { 21 | padding-left: 0px; 22 | padding-right: 0px; 23 | 24 | } 25 | img { 26 | width : 50px; 27 | padding: 20px; 28 | 29 | @media screen and (max-width: 1000px) { 30 | padding: 0px; 31 | position: absolute; 32 | left: 30px; 33 | } 34 | } 35 | .log__body { 36 | padding-top: 75px; 37 | display: flex; 38 | flex-direction: column; 39 | 40 | .email__address { 41 | display: flex; 42 | flex-direction: row; 43 | 44 | 45 | .envelope{ 46 | display: flex; 47 | position: absolute; 48 | margin-top: 10px; 49 | color: #A1A1AA; 50 | margin-left: 10px; 51 | width: 15px; 52 | } 53 | input { 54 | background: #FAFAFA; 55 | border: 1px solid #D4D4D8; 56 | border-radius: 5px; 57 | padding-left: 35px; 58 | width: 300px; 59 | height: 40px; 60 | outline: none; 61 | } 62 | 63 | } 64 | .password__tag { 65 | display: flex; 66 | flex-direction: row; 67 | padding-top: 15px; 68 | 69 | .password__lock { 70 | position: absolute; 71 | display: flex; 72 | margin-top: 10px; 73 | color: #A1A1AA; 74 | margin-left: 10px; 75 | width: 15px; 76 | } 77 | input { 78 | background: #FAFAFA; 79 | border: 1px solid #D4D4D8; 80 | border-radius: 5px; 81 | padding-left: 35px; 82 | width: 300px; 83 | height: 40px; 84 | outline: none; 85 | } 86 | .show__hide { 87 | cursor: pointer; 88 | position: relative; 89 | color: #A1A1AA; 90 | margin-left: -24px; 91 | margin-top: 10px; 92 | width: 20px; 93 | 94 | } 95 | } 96 | .forgot__password { 97 | display: flex; 98 | flex-direction: row; 99 | justify-content: space-between; 100 | .remember__me { 101 | display: flex; 102 | input { 103 | margin-top: 15px; 104 | cursor: pointer; 105 | width: 18px; 106 | height: 18px; 107 | } 108 | 109 | p{ 110 | padding-left: 8px; 111 | font-size: 13px; 112 | margin-top: 17px; 113 | } 114 | } 115 | p { 116 | color : #18181B; 117 | cursor: pointer; 118 | font-size: 13px; 119 | margin-top: 17px; 120 | } 121 | } 122 | button { 123 | display: flex; 124 | cursor: pointer; 125 | background: #18181B; 126 | width: 100%; 127 | justify-content: center; 128 | padding: 7px; 129 | border-radius: 10px; 130 | font-weight: bold; 131 | outline: none; 132 | color: #fff; 133 | -webkit-appearance: button; 134 | border: none; 135 | margin-top: 17px; 136 | height: 40px; 137 | align-items: center; 138 | align-content: center; 139 | } 140 | .sign__in__google { 141 | display: flex; 142 | flex-direction: column; 143 | .conditionals { 144 | display: flex; 145 | text-align: center; 146 | justify-content: center; 147 | font-size: 13px; 148 | padding: 0px; 149 | } 150 | button { 151 | 152 | display: flex; 153 | flex-direction: row; 154 | width: 100%; 155 | text-align: center; 156 | justify-content: center; 157 | margin-top: 0px; 158 | background: rgb(72, 72, 150); 159 | .google__text { 160 | display: flex; 161 | text-transform: uppercase; 162 | } 163 | img { 164 | display: flex; 165 | width: 20px; 166 | margin-top: 2px; 167 | padding: 0px; 168 | 169 | @media screen and (max-width: 1000px) { 170 | padding: 0px; 171 | position: unset; 172 | left: unset; 173 | } 174 | } 175 | } 176 | } 177 | .signup__route { 178 | padding-top: 50px; 179 | font-size: 14px; 180 | .signup__link { 181 | cursor: pointer; 182 | padding-left: 5px; 183 | font-weight: 300; 184 | font-family: TT Firs Neue,'Courier New'; 185 | } 186 | } 187 | } 188 | } 189 | .login__component2 { 190 | position: relative; 191 | border-radius: 10px; 192 | display: flex; 193 | width: 50vw; 194 | height: 100vh; 195 | background: url('../../assets/young-picture.png'); 196 | background-repeat: no-repeat; 197 | background-size: cover; 198 | @media screen and (max-width : 1000px) { 199 | display: none; 200 | } 201 | .layer { 202 | background: linear-gradient(90deg, #44BCFF -0.55%, #44B0FF 22.86%, #FF44EC 48.36%, #FF44EC 73.33%, #FF675E 99.34%); 203 | opacity: 0.9; 204 | filter: blur(70.333px); 205 | transform: matrix(1, 0, 0, 1, 0, 0); 206 | position: absolute; 207 | height: 208.42px; 208 | left: 0px; 209 | top: 490.97px; 210 | width: 50vw; 211 | } 212 | 213 | } 214 | } -------------------------------------------------------------------------------- /client/src/components/product/product-display/product-display.scss: -------------------------------------------------------------------------------- 1 | .display { 2 | width: 95%; 3 | display: grid; 4 | padding-top: 10px; 5 | margin-bottom: 10vh; 6 | margin-left: auto; 7 | margin-right: auto; 8 | grid-template-columns: repeat(5, minmax(0, 1fr)); 9 | background-color: white; 10 | @media only screen and (max-width: 768px) { 11 | grid-template-columns: repeat(2, minmax(0, 1fr)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client/src/components/product/product-display/product-display.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Item from "../product-item/product-item"; 3 | import "./product-display.scss"; 4 | 5 | interface Prop { 6 | products: Array; 7 | } 8 | const ProductDisplay = ({ products }) => { 9 | return ( 10 |
11 | {/* dummy array being mapped */} 12 | {products.map((item, i) => ( 13 | 21 | ))} 22 | {/* End of mapping */} 23 |
24 | ); 25 | }; 26 | 27 | export default ProductDisplay; 28 | -------------------------------------------------------------------------------- /client/src/components/product/product-footer/product-footer.scss: -------------------------------------------------------------------------------- 1 | .product-footer { 2 | width: 100%; 3 | height: 20vh; 4 | .div-1 { 5 | display: flex; 6 | justify-content: space-between; 7 | border: solid; 8 | align-items: center; 9 | border-left: none; 10 | border-right: none; 11 | border-color: rgba(0, 0, 0, 0.12); 12 | padding: 10px; 13 | border-width: 1px; 14 | .isell { 15 | padding: 10px; 16 | padding-top: 30px; 17 | padding-bottom: 30px; 18 | height: 30px; 19 | width: 70px; 20 | } 21 | .isell-text { 22 | font-style: normal; 23 | font-weight: 300; 24 | font-size: 14px; 25 | line-height: 22px; 26 | /* or 157% */ 27 | 28 | 29 | /* gray/600 */ 30 | 31 | color: #52525B; 32 | } 33 | } 34 | .copy-text { 35 | margin-bottom: 10px; 36 | display: flex; 37 | justify-content: center; 38 | align-items: center; 39 | width: 100%; 40 | font-style: normal; 41 | font-weight: 400; 42 | font-size: 14px; 43 | line-height: 22px; 44 | /* identical to box height, or 157% */ 45 | 46 | text-align: center; 47 | 48 | /* gray/500 */ 49 | 50 | color: #71717A; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /client/src/components/product/product-footer/product-footer.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./product-footer.scss"; 3 | const ProductFooter = () => { 4 | const iSELLlogo = require("../../../assets/isell-logo.png"); 5 | return ( 6 |
7 |
8 | isell 9 |

10 | iSELL gives you the building blocks to build a truly profitable 11 | business. 12 |

13 |
14 |

15 | © Copyright 2022, All Rights Reserved by iSELL 16 |

17 |
18 | ); 19 | }; 20 | 21 | export default ProductFooter; 22 | -------------------------------------------------------------------------------- /client/src/components/product/product-item/product-item.scss: -------------------------------------------------------------------------------- 1 | .item { 2 | height: fit-content; 3 | grid-column: span 1 / span 1; 4 | margin: 10px; 5 | margin-top: 30px; 6 | @media only screen and (max-width: 1024px) { 7 | } 8 | @media only screen and (max-width: 768px) { 9 | } 10 | .div-1 { 11 | border-radius: 7px; 12 | background: #f4f4f4; 13 | padding-top: 1px; 14 | padding-left: 7px; 15 | padding-right: 7px; 16 | height: 200px; 17 | .text-1 { 18 | font-weight: bold; 19 | width: fit-content; 20 | background-color: #ffff; 21 | padding: 1px; 22 | font-size: 12px; 23 | } 24 | .image { 25 | width: 80%; 26 | height: 141px; 27 | margin-left: 29px; 28 | border-radius: 10px; 29 | @media only screen and (max-width: 768px) { 30 | width: 70%; 31 | height: 100px; 32 | } 33 | @media only screen and (max-width: 1027px) { 34 | height: 150px; 35 | } 36 | margin-left: 29px; 37 | } 38 | } 39 | .div-2 { 40 | width: 100%; 41 | display: flex; 42 | height: 7vh; 43 | @media only screen and (max-width: 1026px) { 44 | height: fit-content; 45 | } 46 | @media only screen and (max-width: 768px) { 47 | margin-bottom: 16px; 48 | width: 40%; 49 | } 50 | @media only screen and (max-width: 1026px) { 51 | margin-bottom: 0px; 52 | } 53 | .item-name { 54 | flex: 1; 55 | font-size: small; 56 | } 57 | .item-price { 58 | margin-left: 4px; 59 | font-size: small; 60 | } 61 | } 62 | .buy-btn { 63 | text-transform: capitalize; 64 | cursor: pointer; 65 | background: #18181b; 66 | border-radius: 5px; 67 | color: white; 68 | padding: 5px; 69 | font-size: 11px; 70 | &:hover, &:active{ 71 | background-color: whitesmoke; 72 | color: black; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /client/src/components/product/product-item/product-item.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useDispatch } from "react-redux"; 3 | import "./product-item.scss"; 4 | import { addToCart } from "../../../store/basket/basket"; 5 | import {alert, close} from '../../../store/alert/alert.modal.reducer' 6 | interface Items { 7 | id: any; 8 | itemType: string; 9 | imageUrl: string; 10 | name: string; 11 | price: number; 12 | } 13 | const Item = ({ id, itemType, imageUrl, name, price }: Items) => { 14 | const dispatch = useDispatch(); 15 | const addToCartt = () => { 16 | dispatch( 17 | addToCart({ 18 | id: id, 19 | title: name, 20 | image: imageUrl, 21 | price: price, 22 | rating: itemType, 23 | }) 24 | ); 25 | dispatch(alert("Items Added +")) 26 | setTimeout(() => { 27 | dispatch(close("")) 28 | }, 2000) 29 | console.log("added"); 30 | }; 31 | return ( 32 |
33 |
34 | {/*

{itemType}

*/} 35 | product 36 |
37 |
38 |

{name}

39 |

${price}

40 |
41 | 44 |
45 | ); 46 | }; 47 | 48 | export default Item; 49 | -------------------------------------------------------------------------------- /client/src/components/product/product-items/product-items.scss: -------------------------------------------------------------------------------- 1 | .product-item { 2 | width: 95%; 3 | margin: auto; 4 | margin-bottom: 30px; 5 | .product { 6 | width: 100%; 7 | height: 180px; 8 | padding-top: 10px; 9 | .user-header { 10 | display: flex; 11 | flex-direction: column; 12 | align-items: center; 13 | padding: 10px; 14 | color: white; 15 | width: 98%; 16 | margin: auto; 17 | opacity: 0.8; 18 | background: linear-gradient( 19 | 90deg, 20 | #44bcff -0.55%, 21 | #44b0ff 22.86%, 22 | #ff44ec 48.36%, 23 | #ff44ec 73.33%, 24 | #ff675e 99.34% 25 | ); 26 | border-radius: 8px; 27 | img { 28 | height: 70px; 29 | border-radius: 100%; 30 | width: 70px; 31 | } 32 | .product-title { 33 | // font-family: "Plus Jakarta Sans"; 34 | // font-style: normal; 35 | font-weight: 700; 36 | font-size: 24px; 37 | line-height: 34px; 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /client/src/components/product/product-items/product-items.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./product-items.scss"; 3 | 4 | interface Props { 5 | name: string; 6 | description: string; 7 | imageUrl: string; 8 | } 9 | const ProductItems = ({ name, description, imageUrl }) => { 10 | const image1 = require("../../../assets/profilep.png"); 11 | return ( 12 |
13 |
14 |
15 | profile 16 |

{name}

17 |

{description}

18 |
19 |
20 |
21 | ); 22 | }; 23 | 24 | export default ProductItems; 25 | -------------------------------------------------------------------------------- /client/src/components/product/product.components.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Navigate, useLocation, useNavigate } from "react-router-dom"; 3 | import Navbar from "../home/navbar/navbar.component"; 4 | import ProductDisplay from "./product-display/product-display"; 5 | import ProductFooter from "./product-footer/product-footer"; 6 | import ProductItems from "./product-items/product-items"; 7 | 8 | const Product = () => { 9 | const { state }: any = useLocation(); 10 | const Navigate = useNavigate() 11 | return ( 12 | <> 13 | { 14 | !state ? window.location.pathname = '/stores' : 15 |
16 | < Navbar isActive={true} state={state} /> 17 | 22 | 23 | 24 | 25 |
26 | 27 | } 28 | 29 | ); 30 | }; 31 | 32 | export default Product; 33 | -------------------------------------------------------------------------------- /client/src/components/product/product.scss: -------------------------------------------------------------------------------- 1 | .product { 2 | button:hover, button:active{ 3 | background-color: whitesmoke; 4 | color: black; 5 | } 6 | background-color: #ff44ec; 7 | width: 300px; 8 | height: 200px; 9 | .user-header { 10 | background: linear-gradient( 11 | 90deg, 12 | #44bcff -0.55%, 13 | #44b0ff 22.86%, 14 | #ff44ec 48.36%, 15 | #ff44ec 73.33%, 16 | #ff675e 99.34% 17 | ); 18 | opacity: 0.6; 19 | border-radius: 10px; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /client/src/components/register/register.scss: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | .register { 5 | display: flex; 6 | flex-direction: row; 7 | background-color: #fff; 8 | justify-content: space-between; 9 | 10 | @media screen and (max-width: 1000px) { 11 | text-align: center; 12 | justify-content: center; 13 | } 14 | 15 | .register__component1 { 16 | display: flex; 17 | flex-direction: column; 18 | padding: 50px; 19 | 20 | @media screen and (max-width: 1000px) { 21 | padding-left: 0px; 22 | padding-right: 0px; 23 | } 24 | img { 25 | display: flex; 26 | padding: 20px; 27 | width : 50px; 28 | 29 | @media screen and (max-width: 1000px) { 30 | padding: 0px; 31 | position: absolute; 32 | left: 30px; 33 | } 34 | } 35 | .form__tag { 36 | display: flex; 37 | flex-direction: column; 38 | padding-top: 25px; 39 | 40 | .full__name { 41 | display: flex; 42 | flex-direction: row; 43 | padding-bottom: 15px; 44 | 45 | .user { 46 | display: flex; 47 | position: absolute; 48 | margin-top: 10px; 49 | color: #A1A1AA; 50 | margin-left: 10px; 51 | width: 15px; 52 | } 53 | input { 54 | background: #FAFAFA; 55 | border: 1px solid #D4D4D8; 56 | border-radius: 5px; 57 | padding-left: 35px; 58 | width: 300px; 59 | height: 40px; 60 | outline: none; 61 | } 62 | 63 | } 64 | .email__address { 65 | display: flex; 66 | flex-direction: row; 67 | 68 | 69 | .envelope{ 70 | display: flex; 71 | position: absolute; 72 | margin-top: 10px; 73 | color: #A1A1AA; 74 | margin-left: 10px; 75 | width: 15px; 76 | } 77 | input { 78 | background: #FAFAFA; 79 | border: 1px solid #D4D4D8; 80 | border-radius: 5px; 81 | padding-left: 35px; 82 | width: 300px; 83 | height: 40px; 84 | outline: none; 85 | } 86 | 87 | } 88 | .password__tag { 89 | display: flex; 90 | flex-direction: row; 91 | padding-top: 15px; 92 | 93 | .password__lock { 94 | position: absolute; 95 | display: flex; 96 | margin-top: 10px; 97 | color: #A1A1AA; 98 | margin-left: 10px; 99 | width: 15px; 100 | } 101 | input { 102 | background: #FAFAFA; 103 | border: 1px solid #D4D4D8; 104 | border-radius: 5px; 105 | padding-left: 35px; 106 | width: 300px; 107 | height: 40px; 108 | outline: none; 109 | } 110 | .show__hide { 111 | cursor: pointer; 112 | position: relative; 113 | color: #A1A1AA; 114 | margin-left: -24px; 115 | margin-top: 10px; 116 | width: 20px; 117 | 118 | } 119 | } 120 | button { 121 | display: flex; 122 | cursor: pointer; 123 | background: #18181B; 124 | width: 100%; 125 | justify-content: center; 126 | font-weight: bold; 127 | height: 40px; 128 | align-items: center; 129 | align-content: center; 130 | padding: 7px; 131 | border-radius: 10px; 132 | outline: none; 133 | color: #fff; 134 | -webkit-appearance: button; 135 | border: none; 136 | margin-top: 17px; 137 | } 138 | .sign__in__google { 139 | display: flex; 140 | flex-direction: column; 141 | .conditionals { 142 | display: flex; 143 | text-align: center; 144 | justify-content: center; 145 | font-size: 13px; 146 | padding: 0px; 147 | } 148 | button { 149 | display: flex; 150 | flex-direction: row; 151 | width: 100%; 152 | text-align: center; 153 | justify-content: center; 154 | margin-top: 0px; 155 | background: rgb(72, 72, 150); 156 | .google__text { 157 | display: flex; 158 | text-transform: uppercase; 159 | } 160 | img { 161 | display: flex; 162 | width: 20px; 163 | margin-top: 2px; 164 | padding: 0px; 165 | 166 | @media screen and (max-width: 1000px) { 167 | padding: 0px; 168 | position: unset; 169 | left: unset; 170 | } 171 | } 172 | } 173 | } 174 | .signup__route { 175 | padding-top: 50px; 176 | font-size: 14px; 177 | .signup__link { 178 | cursor: pointer; 179 | padding-left: 5px; 180 | font-weight: 300; 181 | font-family: TT Firs Neue,'Courier New'; 182 | } 183 | } 184 | } 185 | 186 | } 187 | .register__component2 { 188 | border-radius: 10px; 189 | position: relative; 190 | margin-top: -316px; 191 | display: flex; 192 | width: 50vw; 193 | height: 145vh; 194 | background: url('../../assets/asian.png'); 195 | background-repeat:no-repeat; 196 | background-size: cover; 197 | @media screen and (max-width : 1000px) { 198 | display: none; 199 | } 200 | .layer { 201 | background: linear-gradient(90deg, #44BCFF -0.55%, #44B0FF 22.86%, #FF44EC 48.36%, #FF44EC 73.33%, #FF675E 99.34%); 202 | opacity: 0.9; 203 | filter: blur(70.333px); 204 | transform: matrix(1, 0, 0, 1, 0, 0); 205 | position: absolute; 206 | height: 208.42px; 207 | left: 0px; 208 | top: 807.97px; 209 | width: 50vw; 210 | } 211 | } 212 | 213 | } -------------------------------------------------------------------------------- /client/src/components/setup/setup.business-type.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | export const businessTypeOption: Array = [ 5 | "Clothing and Fashion", 6 | "Food and Drinks", 7 | "Fintech products", 8 | "Jewelry and accessories", 9 | "Gaming", 10 | "Furniture", 11 | "Agriculture", 12 | "Automobile", 13 | "Others" 14 | ] -------------------------------------------------------------------------------- /client/src/components/setup/setup.scss: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | .setup { 5 | display: flex; 6 | flex-direction: row; 7 | background-color: #fff; 8 | 9 | @media screen and (max-width: 1000px) { 10 | text-align: center; 11 | justify-content: center; 12 | } 13 | 14 | .setup__component1 { 15 | position: relative; 16 | border-radius: 10px; 17 | display: flex; 18 | width: 50vw; 19 | height: 100vh; 20 | background: url('../../assets/setup.jpg'); 21 | background-repeat: no-repeat; 22 | background-size: cover; 23 | @media screen and (max-width : 1000px) { 24 | display: none; 25 | } 26 | } 27 | .setup__component2 { 28 | display: flex; 29 | flex-direction: column; 30 | padding: 75px; 31 | @media screen and (max-width : 1000px) { 32 | text-align: center; 33 | justify-content: center; 34 | align-items: center; 35 | } 36 | .form__tag { 37 | display: flex; 38 | flex-direction: column; 39 | padding-top: 20px; 40 | 41 | .business__name { 42 | display: flex; 43 | flex-direction: row; 44 | padding-bottom: 15px; 45 | 46 | .bus__name { 47 | display: flex; 48 | position: absolute; 49 | margin-top: 10px; 50 | color: #A1A1AA; 51 | margin-left: 10px; 52 | width: 15px; 53 | } 54 | input { 55 | background: #FAFAFA; 56 | border: 1px solid #D4D4D8; 57 | border-radius: 5px; 58 | padding-left: 35px; 59 | width: 300px; 60 | height: 40px; 61 | outline: none; 62 | } 63 | 64 | } 65 | .business__description { 66 | display: flex; 67 | flex-direction: row; 68 | .description { 69 | display: flex; 70 | position: absolute; 71 | margin-top: 15px; 72 | color: #A1A1AA; 73 | margin-left: 10px; 74 | width: 15px; 75 | } 76 | input { 77 | background: #FAFAFA; 78 | border: 1px solid #D4D4D8; 79 | border-radius: 5px; 80 | padding-left: 35px; 81 | width: 300px; 82 | height: 40px; 83 | outline: none; 84 | } 85 | } 86 | .business__type { 87 | display: flex; 88 | flex-direction: row; 89 | padding-top: 15px; 90 | 91 | .type { 92 | display: flex; 93 | position: absolute; 94 | margin-top: 8px; 95 | color: #A1A1AA; 96 | margin-left: 10px; 97 | width: 15px; 98 | } 99 | select { 100 | background: #FAFAFA; 101 | border: 1px solid #D4D4D8; 102 | border-radius: 5px; 103 | padding-left: 32px; 104 | width: 338px; 105 | height: 40px; 106 | outline: none; 107 | -webkit-appearance: menulist-button; 108 | // color: grey; 109 | 110 | option { 111 | color: black ; 112 | } 113 | option:first-child{ 114 | color: grey; 115 | } 116 | } 117 | 118 | } 119 | .business__country{ 120 | display: flex; 121 | flex-direction: row; 122 | padding-top: 15px; 123 | 124 | .country { 125 | display: flex; 126 | position: absolute; 127 | margin-top: 8px; 128 | color: #A1A1AA; 129 | filter: invert(75%) sepia(9%) saturate(200%) hue-rotate(201deg) brightness(76%) contrast(87%); 130 | margin-left: 10px; 131 | width: 15px; 132 | } 133 | 134 | select { 135 | background: #FAFAFA; 136 | border: 1px solid #D4D4D8; 137 | border-radius: 5px; 138 | padding-left: 32px; 139 | width: 338px; 140 | height: 40px; 141 | outline: none; 142 | -webkit-appearance: menulist-button; 143 | // color: grey; 144 | 145 | option { 146 | color: black ; 147 | } 148 | option:first-child{ 149 | color: grey; 150 | } 151 | } 152 | 153 | } 154 | .upload_sect_img { 155 | display: flex; 156 | flex-direction: row; 157 | justify-content: space-between; 158 | padding-top: 15px; 159 | .upload_hd_img { 160 | display: flex; 161 | width: 50px; 162 | height: 50px; 163 | overflow: hidden; 164 | display: flex; 165 | font-size: 20px; 166 | justify-content: center; 167 | align-items: center; 168 | margin-right: 30px; 169 | background: whitesmoke; 170 | border: 1px solid whitesmoke; 171 | border-radius: 5px; 172 | 173 | .image__default { 174 | color: grey; 175 | } 176 | 177 | img { 178 | width: 100%; 179 | } 180 | 181 | } 182 | .upload_add_img { 183 | cursor: pointer; 184 | display: flex; 185 | justify-content: center; 186 | text-transform: uppercase; 187 | background:linear-gradient(90deg, #ebc588 -0.55%, #d9b882 22.86%, #d9b882 48.36%, #dfb97a 73.33%, #dfb97a 99.34%); 188 | font-weight: 550; 189 | padding: 0px 10px; 190 | color: black; 191 | border-radius: 5px; 192 | // margin-right: 22px; 193 | 194 | .upload__p { 195 | font-family: Proxima Soft; 196 | } 197 | } 198 | } 199 | button { 200 | display: flex; 201 | cursor: pointer; 202 | background: #18181B; 203 | height: 40px; 204 | width: 100%; 205 | justify-content: center; 206 | text-align: center; 207 | align-items: center; 208 | padding: 7px; 209 | border-radius: 10px; 210 | font-weight: bold; 211 | outline: none; 212 | color: #fff; 213 | -webkit-appearance: button; 214 | border: none; 215 | margin-top: 17px; 216 | } 217 | 218 | } 219 | } 220 | .logout { 221 | display: flex; 222 | .button__logout { 223 | position: absolute; 224 | top: 10px; 225 | right: 30px; 226 | display: flex; 227 | cursor: pointer; 228 | background: #18181B; 229 | height: 40px; 230 | justify-content: center; 231 | text-align: center; 232 | align-items: center; 233 | padding: 7px; 234 | border-radius: 10px; 235 | font-weight: bold; 236 | outline: none; 237 | color: #fff; 238 | -webkit-appearance: button; 239 | border: none; 240 | margin-top: 17px; 241 | 242 | @media screen and (max-width: 1000px) { 243 | right: 10px; 244 | } 245 | } 246 | } 247 | } -------------------------------------------------------------------------------- /client/src/components/spinner/spinner.scss: -------------------------------------------------------------------------------- 1 | .spinner__overlay { 2 | height: 60vh; 3 | width: 100%; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | 8 | .spinner__container { 9 | display: inline-block; 10 | width: 50px; 11 | height: 50px; 12 | border: 3px solid rgba(195, 195, 195, 0.6); 13 | border-radius: 50%; 14 | border-top-color: #636767; 15 | animation: spin 1s ease-in-out infinite; 16 | -webkit-animation: spin 1s ease-in-out infinite; 17 | @keyframes spin { 18 | to { 19 | -webkit-transform: rotate(360deg); 20 | } 21 | } 22 | @-webkit-keyframes spin { 23 | to { 24 | -webkit-transform: rotate(360deg); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /client/src/components/spinner/spinner.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant modules 5 | import React from "react"; 6 | import './spinner.scss'; 7 | 8 | const Spinner = () => { 9 | return ( 10 |
11 |
12 |
13 | ); 14 | } 15 | 16 | export default Spinner; -------------------------------------------------------------------------------- /client/src/components/stores/store-item/store-item.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-xyzdev/iSELL/dc04ddf6415bc3efb79f2640765c63a3702dbdb5/client/src/components/stores/store-item/store-item.scss -------------------------------------------------------------------------------- /client/src/components/stores/store-item/store-item.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const StoreItem = () => { 4 | return ( 5 |
6 | {/* {products.map((product, i) => ( 7 |
8 |
9 |

{product?.stock}

10 | 11 |
12 |
13 |

{product?.product}

14 |

{product?.price}

15 |
16 |
17 | ))} */} 18 |
19 | ); 20 | }; 21 | 22 | export default StoreItem; 23 | -------------------------------------------------------------------------------- /client/src/components/stores/stores.scss: -------------------------------------------------------------------------------- 1 | .store-com { 2 | padding: 20px; 3 | .div-1 { 4 | .text-1 { 5 | font-size: 14px; 6 | margin-top: 40px; 7 | margin-left: 30px; 8 | } 9 | } 10 | 11 | .products { 12 | display: grid; 13 | // grid-template-columns: 1fr 1fr 1fr 1fr; 14 | // grid-gap: 10px; 15 | grid-template-columns: repeat(9, minmax(0, 1fr)); 16 | width: 80vw; 17 | padding: 80px 10px 0px 10px; 18 | @media only screen and (max-width: 768px) { 19 | width: 96vw; 20 | padding: 40px 0px 0px 0px; 21 | // padding-top: 40px; 22 | grid-template-columns: repeat(4, minmax(0, 1fr)); 23 | } 24 | 25 | .store-p { 26 | grid-column: span 3 / span 3; 27 | @media only screen and (max-width: 768px) { 28 | grid-column: span 2 / span 2; 29 | } 30 | h2 { 31 | padding: 0px; 32 | font-size: 13px; 33 | 34 | margin: 0px; 35 | margin-left: 13px; 36 | // font-weight: bolder; 37 | } 38 | .product { 39 | margin: 10px; 40 | background: whitesmoke; 41 | border: solid 1px whitesmoke; 42 | border-radius: 10px; 43 | display: flex; 44 | flex-direction: column; 45 | // justify-content: center; 46 | // align-content: center; 47 | // text-align: center; 48 | width: 20vw; 49 | @media only screen and (max-width: 768px) { 50 | width: fit-content; 51 | } 52 | height: 250px; 53 | img { 54 | display: flex; 55 | justify-content: center; 56 | margin: auto; 57 | margin-right: auto; 58 | height: 80%; 59 | width: 80%; 60 | border-radius: 5%; 61 | background-image: none !important; 62 | } 63 | } 64 | .product__details { 65 | width: 20vw; 66 | margin-top: 10px 10px 5px 10px; 67 | display: flex; 68 | flex-direction: column; 69 | justify-content: space-between; 70 | 71 | p { 72 | margin-top: 0px; 73 | 74 | margin-left: 13px; 75 | font-size: 11px; 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /client/src/components/stores/stores.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { getStores } from "../../firebase/firebase.utils"; 3 | import { useNavigate } from "react-router-dom"; 4 | 5 | import "./stores.scss"; 6 | import Spinner from "../spinner/spinner"; 7 | 8 | const StoresComponent = () => { 9 | const navigate = useNavigate(); 10 | const [productStores, setProductStores]: any = useState([]); 11 | const [loading, setloading] = useState(false); 12 | let products: any; 13 | const stores = async () => { 14 | setloading(false); 15 | products = await getStores(); 16 | setProductStores(products); 17 | setloading(true) 18 | console.log(products, 'okay'); 19 | }; 20 | 21 | const toProductPage = (product: any) => { 22 | navigate("/product", { 23 | state: product, 24 | }); 25 | }; 26 | useEffect(() => { 27 | stores(); 28 | }, []); 29 | 30 | return ( 31 |
32 | { 33 | !loading ? : 34 |
35 |
36 |

Stores Owned By vendors on ISELL

37 |
38 |
39 | 40 | {productStores.map((product: any, i: any) => ( 41 |
toProductPage(product)} 46 | > 47 |

{product?.businessDetails.business_name}

48 |
49 | 56 |
57 |
58 |

{product?.businessDetails.business_type}

59 |
60 |
61 | 62 | ))} 63 | 64 | 65 |
66 |
67 | } 68 | 69 |
70 | ); 71 | }; 72 | 73 | export default StoresComponent; 74 | -------------------------------------------------------------------------------- /client/src/firebase/firebase.config.types.ts: -------------------------------------------------------------------------------- 1 | // Copyright Paylancers 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | export interface firebaseConfigTypes { 5 | apiKey: string | undefined; 6 | authDomain: string | undefined; 7 | projectId: string | undefined; 8 | storageBucket: string | undefined; 9 | messagingSenderId: string | undefined; 10 | appId: string | undefined; 11 | measurementId: string | undefined; 12 | } 13 | -------------------------------------------------------------------------------- /client/src/firebase/firebase.utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright Paylancers 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //import firebase config types 5 | import { firebaseConfigTypes } from "./firebase.config.types"; 6 | 7 | import { initializeApp } from "firebase/app"; 8 | import { 9 | getAuth, 10 | signInWithRedirect, 11 | signOut, 12 | signInWithPopup, 13 | GoogleAuthProvider, 14 | createUserWithEmailAndPassword, 15 | signInWithEmailAndPassword, 16 | onAuthStateChanged, 17 | sendPasswordResetEmail 18 | } from "firebase/auth"; 19 | 20 | import { 21 | getFirestore, 22 | doc, 23 | getDoc, 24 | setDoc, 25 | DocumentData, 26 | DocumentReference, 27 | arrayUnion, 28 | DocumentSnapshot, 29 | updateDoc, 30 | getDocs, 31 | collection, 32 | } from "firebase/firestore"; 33 | 34 | //storage ref 35 | import { getStorage } from "firebase/storage"; 36 | 37 | // Firebase configuration 38 | export const firebaseConfig: firebaseConfigTypes = { 39 | apiKey: process.env.REACT_APP_apiKey, 40 | authDomain: process.env.REACT_APP_authDomain, 41 | projectId: process.env.REACT_APP_projectId, 42 | storageBucket: process.env.REACT_APP_storageBucket, 43 | messagingSenderId: process.env.REACT_APP_messagingSenderId, 44 | appId: process.env.REACT_APP_appId, 45 | measurementId: process.env.REACT_APP_measurementId, 46 | }; 47 | 48 | // initialize the app 49 | const app = initializeApp(firebaseConfig); 50 | 51 | const googleProvider = new GoogleAuthProvider(); 52 | 53 | googleProvider.setCustomParameters({ 54 | prompt: "select_account", 55 | }); 56 | export const auth = getAuth(); 57 | 58 | // google popup 59 | export const signInWithGooglePopup = () => 60 | signInWithPopup(auth, googleProvider); 61 | 62 | export const signInWithGoogleRedirect = () => 63 | signInWithRedirect(auth, googleProvider); 64 | 65 | // firestore 66 | export const db = getFirestore(); 67 | 68 | // create user document 69 | export const createUserDocumentFromAuth = async ( 70 | userAuth: any, 71 | additionalInformation = {} 72 | ) => { 73 | if (!userAuth) return; 74 | 75 | const userDocRef: DocumentReference = doc( 76 | db, 77 | "users", 78 | userAuth.uid 79 | ); 80 | 81 | const userSnapshot: DocumentSnapshot = await getDoc(userDocRef); 82 | 83 | if (!userSnapshot.exists()) { 84 | const { displayName, email }: any = userAuth; 85 | const createdAt: Date = new Date(); 86 | const verification: boolean = false; 87 | const products: Array = []; 88 | const sales: Array = []; 89 | const businessDetails: Object = { 90 | business_name: "", 91 | business_description: "", 92 | business_url: "", 93 | business_type: "", 94 | business_wallet: "", 95 | }; 96 | 97 | try { 98 | await setDoc(userDocRef, { 99 | displayName, 100 | email, 101 | createdAt, 102 | verification, 103 | businessDetails, 104 | products, 105 | sales, 106 | ...additionalInformation, 107 | }); 108 | } catch (error: any) { 109 | console.log("error creating the user", error.message); 110 | } 111 | } 112 | 113 | return userDocRef; 114 | }; 115 | // get each user data 116 | export const getDataFromUID = async (uid) => { 117 | const userDocRef = doc(db, "users", uid); 118 | 119 | const userSnapshot = await getDoc(userDocRef); 120 | 121 | return userSnapshot.data(); 122 | }; 123 | 124 | // check business verification 125 | export const checkverification = async (uid: any) => { 126 | const userDocRef = doc(db, "users", uid); 127 | 128 | const userSnapshot = await getDoc(userDocRef); 129 | 130 | return userSnapshot.data()?.verification; 131 | }; 132 | 133 | // create user auth with email and password 134 | export const createAuthUserWithEmailAndPassword = async ( 135 | email: string, 136 | password: string 137 | ) => { 138 | if (!email || !password) return; 139 | 140 | return await createUserWithEmailAndPassword(auth, email, password); 141 | }; 142 | 143 | // sign in with email and password 144 | export const signInAuthUserWithEmailAndPassword = async ( 145 | email: string, 146 | password: string 147 | ) => { 148 | if (!email || !password) return; 149 | 150 | return await signInWithEmailAndPassword(auth, email, password); 151 | }; 152 | 153 | //send password reset 154 | export const resetPassword = async (email : string) => { 155 | if(!email) return 156 | return await sendPasswordResetEmail(auth,email ) 157 | } 158 | 159 | //signout 160 | export const signOutUser = async () => await signOut(auth); 161 | 162 | export const onAuthStateChangedListener = (callback: any) => 163 | onAuthStateChanged(auth, callback); 164 | 165 | // storage 166 | export const storage = getStorage(app); 167 | 168 | // adding set up business details to firestore and update verification 169 | export const addSetupDetails = async (uid, values, wallet) => { 170 | console.log(wallet, "firebase"); 171 | const getDocRef = doc(db, "users", uid); 172 | 173 | const userSnapshot = await getDoc(getDocRef); 174 | const { businessName, description, businessLogoUrl, businessType } = values; 175 | 176 | if (!userSnapshot.data()?.verification) { 177 | console.log(values, "values"); 178 | try { 179 | await setDoc( 180 | getDocRef, 181 | { 182 | verification: true, 183 | businessDetails: { 184 | business_name: businessName, 185 | business_description: description, 186 | business_url: businessLogoUrl, 187 | business_type: businessType, 188 | business_wallet: wallet, 189 | }, 190 | }, 191 | { merge: true } 192 | ); 193 | } catch (error: any) { 194 | console.log(error); 195 | } 196 | } 197 | }; 198 | 199 | // add product to firestore 200 | export const addProductDetails = async (uid, values) => { 201 | console.log(values); 202 | const filteredObj = Object.fromEntries( 203 | Object.entries(values).filter(([key]) => !key.includes("imageLogo")) 204 | ); 205 | 206 | const getDocRef: any = doc(db, "users", uid); 207 | const userSnapshot: any = await getDoc(getDocRef); 208 | 209 | if (userSnapshot.data()?.verification) { 210 | try { 211 | await updateDoc(getDocRef, { 212 | products: arrayUnion(filteredObj), 213 | }); 214 | } catch (error) { 215 | console.log(error); 216 | } 217 | } 218 | }; 219 | 220 | // get products 221 | export const getProducts = async (uid) => { 222 | if (!uid) return; 223 | const getDocRef = doc(db, "users", uid); 224 | const userSnapshot = await getDoc(getDocRef); 225 | if (userSnapshot.data()?.verification) { 226 | return userSnapshot.data()?.products; 227 | } 228 | }; 229 | 230 | // get All products 231 | 232 | export const getStores = async () => { 233 | let stores: Array = []; 234 | const querySnapShot: any = await getDocs(collection(db, "users")); 235 | querySnapShot.docs.map((doc) => stores.push(doc.data())); 236 | return stores; 237 | }; 238 | -------------------------------------------------------------------------------- /client/src/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.jpg"; 2 | declare module "*.png"; 3 | declare module "*.svg"; 4 | -------------------------------------------------------------------------------- /client/src/index.scss: -------------------------------------------------------------------------------- 1 | @import url(https://db.onlinewebfonts.com/c/bc3d686231203de67d111be6bec8ecf7?family=TT+Firs+Neue); 2 | @import url(https://db.onlinewebfonts.com/c/4679956de12dd2d8fc06ed0333e1d21b?family=Proxima+Soft); 3 | @import url(https://db.onlinewebfonts.com/c/cef009888ec0e6c3fdbb27db91a57b8f?family=Proxima+Nova+A); 4 | @import url(https://db.onlinewebfonts.com/c/315d8cbb2bb3e24f257a56bf3af89fec?family=TT+Firs); 5 | 6 | body, html{ 7 | overflow-x: hidden; 8 | margin: 0; 9 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 10 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 11 | sans-serif; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | 15 | a { 16 | all : unset; 17 | } 18 | } 19 | App { 20 | overflow-x: hidden; 21 | } 22 | h1, h2 { 23 | font-family: TT Firs Neue ,'sans-serif'; 24 | } 25 | 26 | p { 27 | font-family: TT Firs, 'sans-serif'; 28 | } 29 | button { 30 | font-family: TT Firs, 'sans-serif'; 31 | text-transform: uppercase; 32 | } 33 | 34 | input { 35 | font-family: TT Firs, 'sans-serif'; 36 | } 37 | // input:invalid { 38 | // border: solid 1px green !important; 39 | // } 40 | select, option { 41 | font-family: TT Firs, 'sans-serif'; 42 | } 43 | code { 44 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 45 | monospace; 46 | } 47 | 48 | input::-webkit-outer-spin-button, 49 | input::-webkit-inner-spin-button { 50 | -webkit-appearance: none; 51 | margin: 0; 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /client/src/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // relevant modules and files 5 | import React from "react"; 6 | import ReactDOM from "react-dom/client"; 7 | import App from "./App"; 8 | import { store, Persistor } from "./store/store"; 9 | import { Provider } from "react-redux"; 10 | import { PersistGate } from "redux-persist/integration/react"; 11 | 12 | // styles 13 | import "./index.scss"; 14 | 15 | // building block 16 | const root = ReactDOM.createRoot( 17 | document.getElementById("root") as HTMLElement 18 | ); 19 | root.render( 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | ); 28 | -------------------------------------------------------------------------------- /client/src/pages/check-out/check-out.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CheckOutComponent from "../../components/check-out/check-out.components"; 3 | import Navbar from "../../components/home/navbar/navbar.component"; 4 | 5 | const CheckOut = () => { 6 | return ( 7 | <> 8 | 9 | 10 | 11 | ); 12 | }; 13 | 14 | export default CheckOut; 15 | -------------------------------------------------------------------------------- /client/src/pages/dashboard/DashboardPage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant modules and files 5 | import Dashboard from "../../components/dashboard/dashboard.component"; 6 | 7 | //JSX Component 8 | const DashboardPage = () => { 9 | return( 10 | 11 | ); 12 | } 13 | 14 | export default DashboardPage; -------------------------------------------------------------------------------- /client/src/pages/forgot-password/ForgotPasswordPage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant modules and files 5 | import ForgotPassword from "../../components/forgot-password/forgot-password.component"; 6 | 7 | const ForgotPasswordPage = () => { 8 | return ( 9 | 10 | ); 11 | } 12 | 13 | export default ForgotPasswordPage; -------------------------------------------------------------------------------- /client/src/pages/landing/LandingPage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant modules and files 5 | import * as React from "react"; 6 | // import { Link } from "react-router-dom"; 7 | 8 | //import landing page component 9 | import Home from "../../components/home/home.component"; 10 | // JSX component 11 | const LandingPage = () => { 12 | return ( 13 |
14 | 15 |
16 | ) 17 | }; 18 | 19 | export default LandingPage; 20 | -------------------------------------------------------------------------------- /client/src/pages/login/LoginPage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant modules 5 | import React from "react"; 6 | import Login from "../../components/login/login.component"; 7 | 8 | //JSX Component 9 | const LoginPage = () => { 10 | return ( 11 |
12 | 13 |
14 | ) 15 | } 16 | 17 | 18 | 19 | export default LoginPage; -------------------------------------------------------------------------------- /client/src/pages/register/RegisterPage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | import React from "react"; 4 | import Register from "../../components/register/register.component"; 5 | 6 | const RegisterPage = () => { 7 | return ( 8 |
9 | 10 |
11 | ) 12 | } 13 | 14 | export default RegisterPage; 15 | 16 | -------------------------------------------------------------------------------- /client/src/pages/setup/SetupPage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant modules 5 | import React from "react"; 6 | import Setup from "../../components/setup/setup.component"; 7 | 8 | //JSX component 9 | const SetUpPage = () => { 10 | return ( 11 | 12 | ) 13 | } 14 | 15 | export default SetUpPage; -------------------------------------------------------------------------------- /client/src/pages/stores/stores.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Navbar from "../../components/home/navbar/navbar.component"; 3 | import StoresComponent from "../../components/stores/stores"; 4 | 5 | const Stores = () => { 6 | return ( 7 | <> 8 | 9 | 10 | 11 | ); 12 | }; 13 | 14 | export default Stores; 15 | -------------------------------------------------------------------------------- /client/src/rapyd-hooks/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // adding config types 5 | interface configTypes { 6 | rootURL : string 7 | } 8 | export const config: configTypes= { 9 | rootURL : 'https://isellbackend.herokuapp.com', 10 | } -------------------------------------------------------------------------------- /client/src/rapyd-hooks/create-checkout.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant modules 5 | import {config } from './config'; 6 | 7 | export const createCheckoutPage =async (ewallet, amount, items) => { 8 | const body = { 9 | amount : amount, 10 | ewallet : ewallet, 11 | items : items, 12 | } 13 | const response = await fetch(`${config.rootURL}/checkout/customer`, { 14 | method: 'post', 15 | headers : { 16 | 'Content-Type' : 'application/json' 17 | }, 18 | body : JSON.stringify(body) 19 | }) 20 | const data = await response.json() 21 | console.log('wallet', data.checkoutLink) 22 | return data.checkoutLink.redirect_url 23 | } -------------------------------------------------------------------------------- /client/src/rapyd-hooks/create-vendor.wallet.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant modules 5 | import {config } from './config'; 6 | 7 | 8 | export const createVendorWallet = async (values, user) => { 9 | // const dispatch = useDispatch(); 10 | // console.log(values, user) 11 | // console.log(values?.selectedCountry) 12 | const body = { 13 | business_name : values.businessName, 14 | business_country : values?.selectedCountry, 15 | business_type : values?.businessType, 16 | owner_name : user?.displayName, 17 | owner_email : user?.email, 18 | createdAt: values?.createdAt 19 | } 20 | const response = await fetch(`${config.rootURL}/wallet`, { 21 | method: 'post', 22 | headers : { 23 | 'Content-Type' : 'application/json' 24 | }, 25 | body : JSON.stringify(body) 26 | }) 27 | const data = await response.json() 28 | console.log('wallet', data.wallet) 29 | return data.wallet 30 | // const response : any = await axios.post(`${config.rootURL}/wallet`, { 31 | // business_name : values.businessName, 32 | // business_country : values?.selectedCountry, 33 | // business_type : values?.businessType, 34 | // owner_name : user?.displayName, 35 | // owner_email : user?.email, 36 | // createdAt: values?.createdAt 37 | // }).then( (response) => { 38 | // console.log(response.data.wallet, 'wallet') 39 | // return response.data.wallet 40 | // // callback() 41 | // }).catch((error) => { 42 | // console.log(error) 43 | // }) 44 | } -------------------------------------------------------------------------------- /client/src/statics/AlertModal.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant module 5 | import React from "react"; 6 | import { useSelector, useDispatch } from "react-redux"; 7 | import { RootState } from "../store/store"; 8 | 9 | // JSX Component AlertModal 10 | const AlertModal = () => { 11 | 12 | const modalAlert: any = useSelector( 13 | (state: RootState) => state.alert.alertModal.openModal 14 | ); 15 | const modalContent: any = useSelector( 16 | (state: RootState) => state.alert.alertModal.modalContent 17 | ); 18 | // Starting React-dispatch to dispatch action in state in the component 19 | const dispatch = useDispatch(); 20 | 21 | return( 22 |
42 |

{modalContent}

43 |
44 | ) 45 | } 46 | 47 | export default AlertModal; -------------------------------------------------------------------------------- /client/src/statics/ErrorMessage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant module 5 | import React from "react"; 6 | import { useSelector } from "react-redux"; 7 | import { RootState } from "../store/store"; 8 | 9 | // JSX Component AlertModal 10 | const ErrorMessage = () => { 11 | 12 | const modalAlert: any = useSelector( 13 | (state: RootState) => state.error.errorMessage.openModal 14 | ); 15 | const modalContent: any = useSelector( 16 | (state: RootState) => state.error.errorMessage.modalContent 17 | ); 18 | 19 | 20 | return( 21 |
41 |

{modalContent}

45 |
46 | ) 47 | } 48 | 49 | export default ErrorMessage; -------------------------------------------------------------------------------- /client/src/store/alert/alert.modal.reducer.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant module 5 | import { createSlice, PayloadAction } from '@reduxjs/toolkit'; 6 | import { ALERT_ACTION_TYPES } from './alert.modal.types'; 7 | 8 | // user types 9 | interface alertTypes { 10 | alertModal : { openModal: boolean, modalContent: any }, 11 | } 12 | 13 | // initial state 14 | const initialState: alertTypes= { 15 | alertModal : {openModal : false, modalContent: ""} 16 | } 17 | 18 | // setting user actions 19 | export const alertSlice= createSlice({ 20 | name: ALERT_ACTION_TYPES.ALERT_TYPE, 21 | initialState, 22 | reducers : { 23 | alert : (state :any, action :PayloadAction) => { 24 | state.alertModal.openModal = true 25 | state.alertModal.modalContent= action.payload 26 | }, 27 | close : (state :any, action :PayloadAction) => { 28 | state.alertModal.openModal = false 29 | } 30 | } 31 | 32 | 33 | }) 34 | 35 | // dispatch 36 | export const {alert, close} = alertSlice.actions 37 | 38 | //reducer 39 | export default alertSlice.reducer -------------------------------------------------------------------------------- /client/src/store/alert/alert.modal.types.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | export const ALERT_ACTION_TYPES = { 5 | ALERT_TYPE: "ALERT_TYPE", 6 | }; 7 | -------------------------------------------------------------------------------- /client/src/store/basket/basket-types.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | export const BASKET_ACTION_TYPES = { 5 | BASKET_TYPE: "Basket", 6 | }; 7 | -------------------------------------------------------------------------------- /client/src/store/basket/basket.ts: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | import { BASKET_ACTION_TYPES } from "./basket-types"; 3 | 4 | // user types 5 | interface currentBasketType { 6 | basket: Array; 7 | } 8 | 9 | // initial state 10 | const initialState: currentBasketType = { 11 | basket: [], 12 | }; 13 | 14 | // setting user actions 15 | export const basketSlice = createSlice({ 16 | name: BASKET_ACTION_TYPES.BASKET_TYPE, 17 | initialState, 18 | reducers: { 19 | addToCart: (state: any, action: any) => { 20 | const itemInCart = state.basket.find( 21 | (item: any) => item.id === action.payload.id 22 | ); 23 | if (itemInCart) { 24 | itemInCart.quantity++; 25 | } else { 26 | state.basket.push({ ...action.payload, quantity: 1 }); 27 | } 28 | }, 29 | incrementQuantity: (state: any, action: any) => { 30 | const item = state.basket.find((item) => item.id === action.payload); 31 | item.quantity++; 32 | }, 33 | decrementQuantity: (state: any, action: any) => { 34 | const item = state.basket.find((item: any) => item.id === action.payload); 35 | if (item.quantity === 1) { 36 | item.quantity = 1; 37 | } else { 38 | item.quantity--; 39 | } 40 | }, 41 | removeItem: (state: any, action: any) => { 42 | const removeItem = state.basket.filter( 43 | (item: any) => item.id !== action.payload 44 | ); 45 | state.basket = removeItem; 46 | }, 47 | }, 48 | }); 49 | 50 | export const getTotalBasketPrice = (basket) => { 51 | let bask: Array = []; 52 | basket.forEach((element) => { 53 | bask.push(element.price * element.quantity); 54 | }); 55 | return bask?.reduce((amount, item) => item + amount, 0); 56 | }; 57 | // dispatch 58 | export const { addToCart, removeItem, decrementQuantity, incrementQuantity } = 59 | basketSlice.actions; 60 | //reducer 61 | export default basketSlice.reducer; 62 | -------------------------------------------------------------------------------- /client/src/store/error-message/error-message.reducer.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant module 5 | import { createSlice, PayloadAction } from '@reduxjs/toolkit'; 6 | import { ERROR_ACTION_TYPES } from './error-message.types'; 7 | 8 | // user types 9 | interface errorTypes { 10 | errorMessage: { openModal: boolean, modalContent: any }, 11 | } 12 | 13 | // initial state 14 | const initialState: errorTypes= { 15 | errorMessage : {openModal : false, modalContent: ""} 16 | } 17 | 18 | // setting user actions 19 | export const errorSlice= createSlice({ 20 | name: ERROR_ACTION_TYPES.ERROR_TYPE, 21 | initialState, 22 | reducers : { 23 | error : (state :any, action :PayloadAction) => { 24 | state.errorMessage.openModal = true 25 | state.errorMessage.modalContent= action.payload 26 | }, 27 | closeModal : (state :any, action :PayloadAction) => { 28 | state.errorMessage.openModal = false 29 | } 30 | } 31 | 32 | 33 | }) 34 | 35 | // dispatch 36 | export const {error, closeModal} = errorSlice.actions 37 | 38 | //reducer 39 | export default errorSlice.reducer -------------------------------------------------------------------------------- /client/src/store/error-message/error-message.types.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | export const ERROR_ACTION_TYPES = { 5 | ERROR_TYPE: "ERROR_TYPE", 6 | }; 7 | -------------------------------------------------------------------------------- /client/src/store/store.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | //importing relevant modules + functions 5 | 6 | import { configureStore } from "@reduxjs/toolkit"; 7 | import { 8 | persistStore, 9 | persistReducer, 10 | FLUSH, 11 | REHYDRATE, 12 | PAUSE, 13 | PERSIST, 14 | PURGE, 15 | REGISTER, 16 | } from "redux-persist"; 17 | import storage from "redux-persist/lib/storage"; 18 | import userReducer from "./user/user.reducer"; 19 | import alertModalReducer from "./alert/alert.modal.reducer"; 20 | import errorMessageReducer from "./error-message/error-message.reducer"; 21 | import basketReducer from "./basket/basket"; 22 | 23 | 24 | const presistConfig = { 25 | key: "main-root", 26 | storage, 27 | }; 28 | 29 | const cartReducer = persistReducer(presistConfig, basketReducer); 30 | const userReduce = persistReducer(presistConfig, userReducer) 31 | 32 | //creating store 33 | export const store = configureStore({ 34 | reducer: { 35 | currentUser: userReduce, 36 | basket: cartReducer, 37 | alert: alertModalReducer, 38 | error : errorMessageReducer 39 | }, 40 | middleware: (getDefaultMiddleware) => 41 | getDefaultMiddleware({ 42 | serializableCheck: { 43 | ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], 44 | }, 45 | }), 46 | }); 47 | 48 | const Persistor = persistStore(store); 49 | 50 | export { Persistor }; 51 | // exporting types for dispatch and state 52 | export type RootState = ReturnType; 53 | export type AppDispatch = typeof store.dispatch; 54 | -------------------------------------------------------------------------------- /client/src/store/user/user.reducer.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant module 5 | import { createSlice, PayloadAction } from '@reduxjs/toolkit'; 6 | import { USER_ACTION_TYPES } from './user.types'; 7 | 8 | // user types 9 | interface currentUserTypes { 10 | currentUser : null 11 | } 12 | 13 | // initial state 14 | const initialState: currentUserTypes= { 15 | currentUser : null 16 | } 17 | 18 | // setting user actions 19 | export const userSlice = createSlice({ 20 | name: USER_ACTION_TYPES.SET_CURRENT_USER, 21 | initialState, 22 | reducers : { 23 | setCurrentUser : (state :any, action :PayloadAction) => { 24 | state.currentUser = action.payload 25 | } 26 | } 27 | 28 | }) 29 | 30 | // dispatch 31 | export const {setCurrentUser} = userSlice.actions 32 | 33 | //reducer 34 | export default userSlice.reducer -------------------------------------------------------------------------------- /client/src/store/user/user.types.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | export const USER_ACTION_TYPES = { 5 | SET_CURRENT_USER: 'SET_CURRENT_USER', 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /client/src/validation/validation.tsx: -------------------------------------------------------------------------------- 1 | export default function validateInfo(values) { 2 | let errors: any = {}; 3 | 4 | if (!values.username.trim()) { 5 | errors.username = "Username required"; 6 | } 7 | // else if (!/^[A-Za-z]+/.test(values.name.trim())) { 8 | // errors.name = 'Enter a valid name'; 9 | // } 10 | 11 | if (!values.email) { 12 | errors.email = "Email required"; 13 | } else if (!/\S+@\S+\.\S+/.test(values.email)) { 14 | errors.email = "Email address is invalid"; 15 | } 16 | if (!values.password) { 17 | errors.password = "Password is required"; 18 | } else if (values.password.length < 6) { 19 | errors.password = "Password needs to be 6 characters or more"; 20 | } 21 | return errors; 22 | } 23 | -------------------------------------------------------------------------------- /client/src/validation/validation2.tsx: -------------------------------------------------------------------------------- 1 | export default function validateInfo(values) { 2 | let errors: any = {}; 3 | if (!values.email) { 4 | errors.email = "Email required"; 5 | } else if (!/\S+@\S+\.\S+/.test(values.email)) { 6 | errors.email = "Email address is invalid"; 7 | } 8 | if (!values.password) { 9 | errors.password = "Password is required"; 10 | } else if (values.password.length < 6) { 11 | errors.password = "Password needs to be 6 characters or more"; 12 | } 13 | return errors; 14 | } 15 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "noImplicitAny": false 19 | }, 20 | "include": ["src"] 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "isell", 3 | "version": "1.0.0", 4 | "description": "iSELL is a merchant payment web application leveraging rapyd APIs", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "install-client": "npm install --prefix client", 9 | "install-server": "npm install --prefix server", 10 | "install": "npm run install-client && npm run install-server", 11 | "start-client": "npm run dev --prefix client", 12 | "start-server": "npm run dev --prefix server", 13 | "dev": "npm run start-server & npm run start-client" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/Samuellyworld/paylancers.git" 18 | }, 19 | "author": "Samuel Aspirin & Kingsley", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/Samuellyworld/paylancers/issues" 23 | }, 24 | "homepage": "https://github.com/Samuellyworld/paylancers#readme", 25 | "dependencies": { 26 | "redux-persist": "^6.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | .package-lock.json 2 | package-lock.json 3 | .env 4 | build 5 | dist 6 | node_modules 7 | .DS_Store 8 | 9 | -------------------------------------------------------------------------------- /server/ProcFile: -------------------------------------------------------------------------------- 1 | web: node dist/server.js -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "isell-backend", 3 | "version": "1.0.0", 4 | "description": "This is the server side of isell merchant", 5 | "main": "index.js", 6 | "scripts": { 7 | "type": "module", 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "build": "npx tsc", 10 | "start": "node ./dist/server.js", 11 | "dist": "tsc -p .", 12 | "dev": "nodemon ./server.ts" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/Samuellyworld/paylancers.git" 17 | }, 18 | "author": "Samuel Aspirin & Kingsley", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/Samuellyworld/paylancers/issues" 22 | }, 23 | "homepage": "https://github.com/Samuellyworld/paylancers#readme", 24 | "devDependencies": { 25 | "@types/cors": "^2.8.12", 26 | "@types/crypto-js": "^4.1.1", 27 | "@types/express": "^4.17.13", 28 | "@types/morgan": "^1.9.3", 29 | "@types/node": "^18.7.16", 30 | "dotenv": "^16.0.2", 31 | "nodemon": "^2.0.19", 32 | "typescript": "^4.8.3" 33 | }, 34 | "dependencies": { 35 | "axios": "^0.27.2", 36 | "cors": "^2.8.5", 37 | "crypto": "^1.0.1", 38 | "crypto-js": "^4.1.1", 39 | "express": "^4.18.1", 40 | "https": "^1.0.0", 41 | "morgan": "^1.10.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /server/server.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant modules 5 | import express, {Express, Response, Request} from 'express'; 6 | import morgan from 'morgan'; 7 | import dotenv from 'dotenv'; 8 | import cors from 'cors'; 9 | import {checkoutRouter} from './src/routes/checkout'; 10 | import {createWalletRouter} from './src/routes/wallet'; 11 | 12 | 13 | // using .env 14 | dotenv.config(); 15 | 16 | // start an express server 17 | const app: Express = express(); 18 | const port = process.env.PORT || 3000; 19 | 20 | //middlewares 21 | app.use(express.json()); 22 | app.use(cors()); 23 | app.use(morgan('combined')); 24 | app.set('json spaces', 4); 25 | 26 | 27 | //create checkout for unique customer 28 | app.use('/checkout/customer', checkoutRouter); 29 | 30 | // create wallet for vendors 31 | app.use('/wallet', createWalletRouter); 32 | 33 | //root url 34 | app.get('/', (req: Request, res: Response) => { 35 | return res.status(200).json('Isell API is running 🗺') 36 | }) 37 | 38 | 39 | app.listen(port , () => { 40 | console.log(`iSELL API is listening on port ${port}`) 41 | }) -------------------------------------------------------------------------------- /server/src/controller/utilities.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant modules 5 | import crypto from 'crypto-js'; 6 | import dotenv from 'dotenv'; 7 | 8 | // config 9 | dotenv.config(); 10 | 11 | // access keys headers 12 | export const accessKey = process.env.accessKey; 13 | export const secretKey = process.env.secretKey; 14 | // export const url_path = "/v1/user"; 15 | // export const http_method = "post"; 16 | export const salt = crypto.lib.WordArray.random(12); 17 | export const idempotency = new Date().getTime().toString(); 18 | export const timestamp = Math.round(new Date().getTime() / 1000); 19 | 20 | export const getSignature = (body, http_method, url_path) => { 21 | 22 | const to_sign = 23 | http_method + url_path + salt + timestamp + accessKey + secretKey + JSON.stringify(body); 24 | let signature = crypto.enc.Hex.stringify( 25 | crypto.HmacSHA256(to_sign, secretKey) 26 | ); 27 | signature = crypto.enc.Base64.stringify(crypto.enc.Utf8.parse(signature)); 28 | return signature; 29 | } 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /server/src/routes/checkout.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant modules 5 | import { Request, Response } from "express"; 6 | import { 7 | getSignature, 8 | timestamp, 9 | accessKey, 10 | salt, 11 | idempotency, 12 | } from "../controller/utilities"; 13 | import express from "express"; 14 | import axios from "axios"; 15 | 16 | export const checkoutRouter = express.Router(); 17 | 18 | // getting all countries 19 | checkoutRouter.post("/", async (req: Request, res: Response) => { 20 | const http_method = "post"; 21 | const url_path = "/v1/checkout"; 22 | console.log(req.body); 23 | const { ewallet, amount, items } = req.body; 24 | const body = { 25 | amount: amount, 26 | complete_payment_url: "https://chukwuemekakingsley.github.io/Success-Page/", 27 | complete_checkout_url: 28 | "https://chukwuemekakingsley.github.io/Success-Page/", 29 | cancel_checkout_url: "https://chukwuemekakingsley.github.io/Success-Page/", 30 | country: "SG", 31 | currency: "USD", 32 | error_payment_url: "https://chukwuemekakingsley.github.io/ErrorPage/", 33 | merchant_reference_id: `${amount}-2022`, 34 | requested_currency: "USD", 35 | metadata: { 36 | merchant_defined: true, 37 | }, 38 | ewallet: ewallet, 39 | payment_method_type_categories: ["card"], 40 | // expiration: 600 41 | // cart_items : [items] 42 | }; 43 | const headers = { 44 | "Content-Type": "application/json", 45 | salt: salt, 46 | timestamp: timestamp, 47 | signature: getSignature(body, http_method, url_path), 48 | access_key: accessKey, 49 | idempotency: idempotency, 50 | }; 51 | 52 | try { 53 | const request: any = { 54 | baseURL: "https://sandboxapi.rapyd.net", 55 | headers, 56 | url: url_path, 57 | method: http_method, 58 | data: body, 59 | }; 60 | 61 | const response = await axios(request); 62 | console.log(response.data); 63 | res.json({ 64 | checkoutLink: response.data.data, 65 | }); 66 | } catch (error) { 67 | res.json(error); 68 | } 69 | }); 70 | -------------------------------------------------------------------------------- /server/src/routes/wallet.ts: -------------------------------------------------------------------------------- 1 | // Copyright iSELL 💳 2022 2 | // 17 U.S.C §§ 101-1511 3 | 4 | // importing relevant modules 5 | import { Request, Response } from "express"; 6 | import { 7 | getSignature, 8 | timestamp, 9 | accessKey, 10 | salt, 11 | idempotency, 12 | } from "../controller/utilities"; 13 | import express from "express"; 14 | import axios from "axios"; 15 | 16 | export const createWalletRouter = express.Router(); 17 | 18 | // getting all countries 19 | createWalletRouter.post("/", async (req: Request, res: Response) => { 20 | const http_method: string = "post"; 21 | const url_path: string = "/v1/user"; 22 | 23 | const { 24 | owner_email, 25 | owner_name, 26 | createdAt, 27 | business_country, 28 | business_name, 29 | business_type, 30 | } = req.body; 31 | 32 | const body = { 33 | first_name: business_name, 34 | last_name: business_name, 35 | ewallet_reference_id: `${business_name}-${createdAt}`, 36 | metadata: { 37 | merchant_defined: true, 38 | }, 39 | type: "company", 40 | contact: { 41 | phone_number: "+14155551234", 42 | email: owner_email, 43 | first_name: business_name, 44 | last_name: business_name, 45 | mothers_name: "kin", 46 | contact_type: "business", 47 | address: { 48 | name: business_name, 49 | line_1: "123 Main Street", 50 | line_2: "", 51 | line_3: "", 52 | city: "Anytown", 53 | state: "NY", 54 | country: business_country, 55 | zip: "12345", 56 | phone_number: "+14155551234", 57 | metadata: { number: 2 }, 58 | canton: "", 59 | district: "", 60 | }, 61 | identification_type: "PA", 62 | identification_number: "1234567890", 63 | date_of_birth: "11/22/2000", 64 | country: "US", 65 | metadata: { 66 | merchant_defined: true, 67 | }, 68 | business_details: { 69 | entity_type: "association", 70 | name: business_name, 71 | registration_number: "4234567779", 72 | industry_category: "company", 73 | industry_sub_category: business_type, 74 | address: { 75 | name: business_name, 76 | line_1: "1234 Main Street", 77 | line_2: "Suite 1200", 78 | line_3: "", 79 | city: "Anytown", 80 | state: "NY", 81 | country: business_country, 82 | zip: "10101", 83 | phone_number: "14155557779", 84 | metadata: { 85 | merchant_defined: true, 86 | }, 87 | }, 88 | }, 89 | }, 90 | }; 91 | 92 | const headers = { 93 | "Content-Type": "application/json", 94 | salt: salt, 95 | timestamp: timestamp, 96 | signature: getSignature(body, http_method, url_path), 97 | access_key: accessKey, 98 | idempotency: idempotency, 99 | }; 100 | 101 | try { 102 | const data = req.body; 103 | console.log(data, "inside"); 104 | const request: any = { 105 | baseURL: "https://sandboxapi.rapyd.net", 106 | headers, 107 | url: url_path, 108 | method: http_method, 109 | data: body, 110 | }; 111 | 112 | const response = await axios(request); 113 | console.log(response.data); 114 | res.json({ 115 | wallet: response.data.data.id, 116 | }); 117 | } catch (error) { 118 | res.json(error); 119 | } 120 | }); 121 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonJs", 4 | "esModuleInterop": true, 5 | "target": "es6", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "outDir": "dist" 9 | }, 10 | "lib": ["es2015"] 11 | } --------------------------------------------------------------------------------