diff --git a/README.md b/README.md index aba1f360..f387bb1c 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ TaaS App is done using Single SPA micro-frontend architecture https://single-spa ### Local Authentication First of all, to authenticate locally we have to run a local authentication service. + - Clone this repository into `taas-app`. - Inside the folder `taas-app/local/login-locally` run `npm run start`. - You would need npm 5+ for it. This would start a local sever on port 5000 which could be used for local Authentication. @@ -76,36 +77,36 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t 1. Run **Frame** App: - ```sh - git clone https://github.com/topcoder-platform/micro-frontends-frame.git - cd micro-frontends-frame - # inside folder "micro-frontends-frame" run: + ```sh + git clone https://github.com/topcoder-platform/micro-frontends-frame.git + cd micro-frontends-frame + # inside folder "micro-frontends-frame" run: - nvm use # or make sure to use Node 10 - npm i # to install dependencies + nvm use # or make sure to use Node 10 + npm i # to install dependencies - # set environment variables: + # set environment variables: - export APPMODE="development" - export APPENV="local-multi" + export APPMODE="development" + export APPENV="local-multi" - npm run local-server + npm run local-server - # this would start frame server on http://localhost:3000 - ``` + # this would start frame server on http://localhost:3000 + ``` - open one more terminal window in the same folder and run: + open one more terminal window in the same folder and run: - ```sh - # set environment variables: + ```sh + # set environment variables: - export APPMODE="development" - export APPENV="local-multi" + export APPMODE="development" + export APPENV="local-multi" - npm run local-client + npm run local-client - # this host frame client code on http://localhost:8080 - ``` + # this host frame client code on http://localhost:8080 + ``` 2. Run **Navbar** micro-app: @@ -135,6 +136,10 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t nvm use # or make sure to use Node 10 npm i # to install dependencies + # set environment variables: + + export STRIPE_PUBLIC_KEY="" + npm run dev # this host TaaS App as http://localhost:8501/taas-app/topcoder-micro-frontends-teams.js @@ -142,16 +147,16 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t 4. Now we have to update the `micro-frontends-frame` app to show our local version of TaaS App, instead of remote one. Update file `micro-frontends-frame/config/micro-frontends-config-local.json`: - ```js - // replace line - "@topcoder/micro-frontends-teams": "https://platform.topcoder-dev.com/taas-app/topcoder-micro-frontends-teams.js", + ```js + // replace line + "@topcoder/micro-frontends-teams": "https://platform.topcoder-dev.com/taas-app/topcoder-micro-frontends-teams.js", - // with line: - "@topcoder/micro-frontends-teams": "http://localhost:8501/taas-app/topcoder-micro-frontends-teams.js", - ``` + // with line: + "@topcoder/micro-frontends-teams": "http://localhost:8501/taas-app/topcoder-micro-frontends-teams.js", + ``` - Now open in the browser http://localhost:8080/taas/myteams. - If you are not logged-in yet, you should be redirected to the login page. - If you cannot see the application and redirect doesn't happen, make sure that file "http://local.topcoder-dev.com:8501/taas-app/topcoder-micro-frontends-teams.js" is loaded successfully in the Network tab. -Congratulations, you successfully run the project. If you had some issue, please, try to go through README of https://github.com/topcoder-platform/micro-frontends-frame and https://github.com/topcoder-platform/micro-frontends-navbar-app. \ No newline at end of file +Congratulations, you successfully run the project. If you had some issue, please, try to go through README of https://github.com/topcoder-platform/micro-frontends-frame and https://github.com/topcoder-platform/micro-frontends-navbar-app. diff --git a/package-lock.json b/package-lock.json index b524184a..d0d5c0df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2695,6 +2695,115 @@ } } }, + "@material-ui/core": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", + "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.11.4", + "@material-ui/system": "^4.12.1", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.2", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0", + "react-transition-group": "^4.4.0" + }, + "dependencies": { + "popper.js": { + "version": "1.16.1-lts", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", + "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" + } + } + }, + "@material-ui/icons": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz", + "integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==", + "requires": { + "@babel/runtime": "^7.4.4" + } + }, + "@material-ui/lab": { + "version": "4.0.0-alpha.60", + "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.60.tgz", + "integrity": "sha512-fadlYsPJF+0fx2lRuyqAuJj7hAS1tLDdIEEdov5jlrpb5pp4b+mRDUqQTUxi4inRZHS1bEXpU8QWUhO6xX88aA==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.2", + "clsx": "^1.0.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + } + }, + "@material-ui/styles": { + "version": "4.11.4", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz", + "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==", + "requires": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.2", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.5.1", + "jss-plugin-camel-case": "^10.5.1", + "jss-plugin-default-unit": "^10.5.1", + "jss-plugin-global": "^10.5.1", + "jss-plugin-nested": "^10.5.1", + "jss-plugin-props-sort": "^10.5.1", + "jss-plugin-rule-value-function": "^10.5.1", + "jss-plugin-vendor-prefixer": "^10.5.1", + "prop-types": "^15.7.2" + }, + "dependencies": { + "csstype": { + "version": "2.6.17", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz", + "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==" + } + } + }, + "@material-ui/system": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz", + "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.2", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + }, + "dependencies": { + "csstype": { + "version": "2.6.17", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz", + "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==" + } + } + }, + "@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==" + }, + "@material-ui/utils": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz", + "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==", + "requires": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + } + }, "@popperjs/core": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz", @@ -2726,6 +2835,19 @@ "type-detect": "4.0.8" } }, + "@stripe/react-stripe-js": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.4.1.tgz", + "integrity": "sha512-FjcVrhf72+9fUL3Lz3xi02ni9tzH1A1x6elXlr6tvBDgSD55oPJuodoP8eC7xTnBIKq0olF5uJvgtkJyDCdzjA==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "@stripe/stripe-js": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.16.0.tgz", + "integrity": "sha512-ZSHbiwTrISoaTbpercmYGuY7QTg7HxfFyNgbJBaYbwHWbzMhpEdGTsmMpaBXIU6iiqwEEDaIyD8O6yJ+H5DWCg==" + }, "@testing-library/dom": { "version": "6.16.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-6.16.0.tgz", @@ -2985,14 +3107,12 @@ "@types/prop-types": { "version": "15.7.3", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", - "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", - "dev": true + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/react": { "version": "16.9.51", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.51.tgz", "integrity": "sha512-lQa12IyO+DMlnSZ3+AGHRUiUcpK47aakMMoBG8f7HGxJT8Yfe+WE128HIXaHOHVPReAW0oDS3KAI0JI2DDe1PQ==", - "dev": true, "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3007,6 +3127,14 @@ "@types/react": "*" } }, + "@types/react-transition-group": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.2.tgz", + "integrity": "sha512-KibDWL6nshuOJ0fu8ll7QnV/LVTo3PzQ9aCPnRUYPfX7eZohHwLIdNHj7pftanREzHNP4/nJa8oeM73uSiavMQ==", + "requires": { + "@types/react": "*" + } + }, "@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -4966,6 +5094,11 @@ "wrap-ansi": "^5.1.0" } }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5709,6 +5842,15 @@ } } }, + "css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "requires": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, "css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -8576,6 +8718,11 @@ "is-extglob": "^2.1.1" } }, + "is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" + }, "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", @@ -11982,6 +12129,84 @@ "verror": "1.10.0" } }, + "jss": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.7.1.tgz", + "integrity": "sha512-5QN8JSVZR6cxpZNeGfzIjqPEP+ZJwJJfZbXmeABNdxiExyO+eJJDy6WDtqTf8SDKnbL5kZllEpAP71E/Lt7PXg==", + "requires": { + "@babel/runtime": "^7.3.1", + "csstype": "^3.0.2", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-camel-case": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.7.1.tgz", + "integrity": "sha512-+ioIyWvmAfgDCWXsQcW1NMnLBvRinOVFkSYJUgewQ6TynOcSj5F1bSU23B7z0p1iqK0PPHIU62xY1iNJD33WGA==", + "requires": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "10.7.1" + } + }, + "jss-plugin-default-unit": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.7.1.tgz", + "integrity": "sha512-tW+dfYVNARBQb/ONzBwd8uyImigyzMiAEDai+AbH5rcHg5h3TtqhAkxx06iuZiT/dZUiFdSKlbe3q9jZGAPIwA==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1" + } + }, + "jss-plugin-global": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.7.1.tgz", + "integrity": "sha512-FbxCnu44IkK/bw8X3CwZKmcAnJqjAb9LujlAc/aP0bMSdVa3/MugKQRyeQSu00uGL44feJJDoeXXiHOakBr/Zw==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1" + } + }, + "jss-plugin-nested": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.7.1.tgz", + "integrity": "sha512-RNbICk7FlYKaJyv9tkMl7s6FFfeLA3ubNIFKvPqaWtADK0KUaPsPXVYBkAu4x1ItgsWx67xvReMrkcKA0jSXfA==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-props-sort": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.7.1.tgz", + "integrity": "sha512-eyd5FhA+J0QrpqXxO7YNF/HMSXXl4pB0EmUdY4vSJI4QG22F59vQ6AHtP6fSwhmBdQ98Qd9gjfO+RMxcE39P1A==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1" + } + }, + "jss-plugin-rule-value-function": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.7.1.tgz", + "integrity": "sha512-fGAAImlbaHD3fXAHI3ooX6aRESOl5iBt3LjpVjxs9II5u9tzam7pqFUmgTcrip9VpRqYHn8J3gA7kCtm8xKwHg==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.7.1", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-vendor-prefixer": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.7.1.tgz", + "integrity": "sha512-1UHFmBn7hZNsHXTkLLOL8abRl8vi+D1EVzWD4WmLFj55vawHZfnH1oEz6TUf5Y61XHv0smdHabdXds6BgOXe3A==", + "requires": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "10.7.1" + } + }, "jsx-ast-utils": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", @@ -16666,6 +16891,11 @@ "setimmediate": "^1.0.4" } }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/package.json b/package.json index a95fce45..7765e741 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,13 @@ "webpack-merge": "^4.2.2" }, "dependencies": { + "@material-ui/core": "^4.12.3", + "@material-ui/icons": "^4.11.2", + "@material-ui/lab": "^4.0.0-alpha.60", "@popperjs/core": "^2.5.4", "@reach/router": "^1.3.4", + "@stripe/react-stripe-js": "^1.4.1", + "@stripe/stripe-js": "^1.16.0", "@toast-ui/editor": "^2.5.1", "axios": "^0.21.0", "classnames": "^2.2.6", diff --git a/src/constants/index.js b/src/constants/index.js index 588c2084..9c993ad3 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -281,6 +281,11 @@ export const ACTION_TYPE = { DELETE_MATCHING_ROLE: "DELETE_MATCHING_ROLE", EDIT_MATCHING_ROLE: "EDIT_MATCHING_ROLE", + /** + * team object + */ + ADD_TEAM_OBJECT: "ADD_TEAM_OBJECT", + /* * global loading state */ diff --git a/src/root.component.jsx b/src/root.component.jsx index 2f5d06a9..369d0bb5 100644 --- a/src/root.component.jsx +++ b/src/root.component.jsx @@ -14,6 +14,7 @@ import CreateTeamLanding from "./routes/CreateNewTeam/pages/CreateTeamLanding"; import InputSkills from "./routes/CreateNewTeam/pages/InputSkills"; import InputJobDescription from "./routes/CreateNewTeam/pages/InputJobDescription"; import SelectRole from "./routes/CreateNewTeam/pages/SelectRole"; +import CreateTaasPayment from "./routes/CreateNewTeam/pages/CreateTaasPayment"; import ReduxToastr from "react-redux-toastr"; import store from "./store"; import "./styles/main.vendor.scss"; @@ -34,6 +35,7 @@ export default function Root() { + diff --git a/src/routes/CreateNewTeam/actions/index.js b/src/routes/CreateNewTeam/actions/index.js index 835cff1e..d025f2fa 100644 --- a/src/routes/CreateNewTeam/actions/index.js +++ b/src/routes/CreateNewTeam/actions/index.js @@ -41,6 +41,16 @@ const editMatchingRole = (role) => ({ payload: role, }); +const addTeamObject = (teamObject) => ({ + type: ACTION_TYPE.ADD_TEAM_OBJECT, + payload: teamObject, +}); + +export const addTeamObjects = (teamObject) => (dispatch, getState) => { + dispatch(addTeamObject(teamObject)); + updateLocalStorage(getState().teamObject); +}; + export const clearSearchedRoles = () => (dispatch, getState) => { dispatch(clearRoles()); updateLocalStorage(getState().searchedRoles); diff --git a/src/routes/CreateNewTeam/components/Progress/index.jsx b/src/routes/CreateNewTeam/components/Progress/index.jsx index 06c1cebe..228a7307 100644 --- a/src/routes/CreateNewTeam/components/Progress/index.jsx +++ b/src/routes/CreateNewTeam/components/Progress/index.jsx @@ -22,14 +22,13 @@ function Progress({ stages, percentage, }) { - - let backgroundIcon + let backgroundIcon; if (extraStyleName === "input-skills") { - backgroundIcon= + backgroundIcon = ; } else if (extraStyleName === "input-job-description") { - backgroundIcon= + backgroundIcon = ; } else { - backgroundIcon= + backgroundIcon = ; } return ( @@ -47,15 +46,19 @@ function Progress({ ))} - - {backgroundIcon} + {buttonLabel !== undefined ? ( + <> + + {backgroundIcon} + + ) : null} ); } diff --git a/src/routes/CreateNewTeam/components/Progress/styles.module.scss b/src/routes/CreateNewTeam/components/Progress/styles.module.scss index d429aea9..65d888bd 100644 --- a/src/routes/CreateNewTeam/components/Progress/styles.module.scss +++ b/src/routes/CreateNewTeam/components/Progress/styles.module.scss @@ -13,22 +13,22 @@ } .input-job-description { - background-image: linear-gradient(135deg, #2984BD 0%, #0AB88A 100%); + background-image: linear-gradient(135deg, #2984bd 0%, #0ab88a 100%); } .input-skills { - background-image: linear-gradient(221.5deg, #646CD0 0%, #9d41c9 100%); + background-image: linear-gradient(221.5deg, #646cd0 0%, #9d41c9 100%); } .role-selection { - background-image: linear-gradient(45deg, #8B41B0 0%, #EF476F 100%); + background-image: linear-gradient(45deg, #8b41b0 0%, #ef476f 100%); } .list { margin-bottom: 55px; & + button[disabled] { - background-color: #E9E9E9; - color: #FFF; + background-color: #e9e9e9; + color: #fff; opacity: 1; filter: none; } @@ -83,3 +83,7 @@ width: 144px; height: 144px; } + +.final-step { + height: 230px; +} diff --git a/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx b/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx index f42dae20..4263abcc 100644 --- a/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx +++ b/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx @@ -91,11 +91,15 @@ function SearchAndSubmit(props) { .then((res) => { const name = _.get(res, "data.name"); const searchId = _.get(res, "data.roleSearchRequestId"); + const imageUrl = _.get(res, "data.imageUrl"); + const rates = _.get(res, "data.rates"); if (name && !isCustomRole({ name })) { dispatch( addSearchedRole({ searchId, name, + imageUrl, + rates, numberOfResources: 1, durationWeeks: 4, }) diff --git a/src/routes/CreateNewTeam/components/SearchContainer/index.jsx b/src/routes/CreateNewTeam/components/SearchContainer/index.jsx index 1a9620f0..eb72a88f 100644 --- a/src/routes/CreateNewTeam/components/SearchContainer/index.jsx +++ b/src/routes/CreateNewTeam/components/SearchContainer/index.jsx @@ -81,9 +81,9 @@ function SearchContainer({ }; const getPercentage = useCallback(() => { - if (searchState === "searching") return "52"; - if (matchingRole) return "98"; - return "88"; + if (searchState === "searching") return "26"; + if (matchingRole) return "53"; + return "84"; }, [searchState, matchingRole]); return ( diff --git a/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx b/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx index 0ab9d217..4bae541c 100644 --- a/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx +++ b/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx @@ -25,7 +25,11 @@ import ConfirmationModal from "../ConfirmationModal"; import { withBusinessAuthentication } from "../../../../hoc/withAuthentication"; import "./styles.module.scss"; import { isCustomRole, isUuid, setCurrentStage } from "utils/helpers"; -import { clearSearchedRoles, editRoleAction } from "../../actions"; +import { + addTeamObjects, + clearSearchedRoles, + editRoleAction, +} from "../../actions"; import { postTeamRequest } from "services/teams"; import NoMatchingProfilesResultCard from "../NoMatchingProfilesResultCard"; @@ -115,18 +119,23 @@ function SubmitContainer({ const requestTeam = useCallback(() => { setRequestLoading(true); - postTeamRequest(teamObject) - .then(() => { - setTimeout(() => { - dispatch(clearSearchedRoles()); - // Backend api create project has sync issue, so delay 2 seconds - navigate("/taas/myteams"); - }, 2000); - }) - .catch((err) => { - setRequestLoading(false); - toastr.error("Error Requesting Team", err.message); - }); + if (matchingRole.isExternalMember) { + dispatch(addTeamObjects(teamObject)); + navigate("/taas/myteams/createnewteam/create-taas-payment"); + } else { + postTeamRequest(teamObject) + .then(() => { + setTimeout(() => { + dispatch(clearSearchedRoles()); + // Backend api create project has sync issue, so delay 2 seconds + navigate("/taas/myteams"); + }, 2000); + }) + .catch((err) => { + setRequestLoading(false); + toastr.error("Error Requesting Team", err.message); + }); + } }, [dispatch, teamObject]); return ( diff --git a/src/routes/CreateNewTeam/components/progress/index.jsx b/src/routes/CreateNewTeam/components/progress/index.jsx index 06c1cebe..228a7307 100644 --- a/src/routes/CreateNewTeam/components/progress/index.jsx +++ b/src/routes/CreateNewTeam/components/progress/index.jsx @@ -22,14 +22,13 @@ function Progress({ stages, percentage, }) { - - let backgroundIcon + let backgroundIcon; if (extraStyleName === "input-skills") { - backgroundIcon= + backgroundIcon = ; } else if (extraStyleName === "input-job-description") { - backgroundIcon= + backgroundIcon = ; } else { - backgroundIcon= + backgroundIcon = ; } return ( @@ -47,15 +46,19 @@ function Progress({ ))} - - {backgroundIcon} + {buttonLabel !== undefined ? ( + <> + + {backgroundIcon} + + ) : null} ); } diff --git a/src/routes/CreateNewTeam/components/progress/styles.module.scss b/src/routes/CreateNewTeam/components/progress/styles.module.scss index d429aea9..65d888bd 100644 --- a/src/routes/CreateNewTeam/components/progress/styles.module.scss +++ b/src/routes/CreateNewTeam/components/progress/styles.module.scss @@ -13,22 +13,22 @@ } .input-job-description { - background-image: linear-gradient(135deg, #2984BD 0%, #0AB88A 100%); + background-image: linear-gradient(135deg, #2984bd 0%, #0ab88a 100%); } .input-skills { - background-image: linear-gradient(221.5deg, #646CD0 0%, #9d41c9 100%); + background-image: linear-gradient(221.5deg, #646cd0 0%, #9d41c9 100%); } .role-selection { - background-image: linear-gradient(45deg, #8B41B0 0%, #EF476F 100%); + background-image: linear-gradient(45deg, #8b41b0 0%, #ef476f 100%); } .list { margin-bottom: 55px; & + button[disabled] { - background-color: #E9E9E9; - color: #FFF; + background-color: #e9e9e9; + color: #fff; opacity: 1; filter: none; } @@ -83,3 +83,7 @@ width: 144px; height: 144px; } + +.final-step { + height: 230px; +} diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/FormField/index.jsx b/src/routes/CreateNewTeam/pages/CreateTaasPayment/FormField/index.jsx new file mode 100644 index 00000000..a07d6978 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/FormField/index.jsx @@ -0,0 +1,45 @@ +import React from "react"; +import TextField from "@material-ui/core/TextField"; +import { makeStyles } from "@material-ui/core/styles"; +import Box from "@material-ui/core/Box"; + +const useStyles = makeStyles(() => ({ + label: { + color: "#AAAAAA", + fontFamily: "Roboto", + fontSize: "14px", + textAlign: "left", + "&.Mui-focused": { + color: "#137D60", + background: "#fffff", + }, + "&.Mui-error": { + color: "#EF476F", + }, + }, +})); + +function FormField({ label, name, handleInputValue, errors }) { + const classes = useStyles(); + return ( + + + + ); +} + +export default FormField; diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/PaymentForm/index.jsx b/src/routes/CreateNewTeam/pages/CreateTaasPayment/PaymentForm/index.jsx new file mode 100644 index 00000000..323510c5 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/PaymentForm/index.jsx @@ -0,0 +1,209 @@ +import React, { useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { + CardNumberElement, + CardExpiryElement, + CardCvcElement, + useStripe, + useElements, +} from "@stripe/react-stripe-js"; +import { navigate } from "@reach/router"; +import { toastr } from "react-redux-toastr"; +import { makeStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import Box from "@material-ui/core/Box"; + +import { postTeamPayment, postTeamRequest } from "services/teams"; +import { clearSearchedRoles } from "../../../actions"; +import StripeElement from "../StripeElement"; +import FormField from "../FormField"; +import SelectField from "../SelectField"; +import ConfirmationModal from "../../../components/ConfirmationModal"; + +import "./styles.module.scss"; + +const useStyles = makeStyles(() => ({ + typography: { + margin: "10px 0px 2px 0px", + color: "#2a2a2a", + fontFamily: "Roboto", + fontSize: "12px", + textAlign: "left", + fontWeight: "500", + }, + button: { + borderRadius: "20px", + width: "258px", + height: "40px", + }, +})); + +const PaymentForm = ({ calculatedAmount }) => { + const initialFormValues = { + email: "", + name: "", + zipcode: "", + formSubmitted: false, + success: false, + }; + + const [formValues, setFormValues] = useState(initialFormValues); + const [dropdownValue, setDropdownValue] = useState(""); + const [processing, setProcessing] = useState(false); + const [requestLoading, setRequestLoading] = useState(false); + const [errors, setErrors] = useState({}); + const stripe = useStripe(); + const elements = useElements(); + const dispatch = useDispatch(); + const { teamObject } = useSelector((state) => state.searchedRoles); + + const handleDropdown = (value) => { + setDropdownValue(value); + }; + + const validate = (fieldValues = formValues) => { + let temp = { + ...errors, + }; + + if ("name" in fieldValues) + temp.name = fieldValues.name ? "" : "This field is require."; + + if ("email" in fieldValues) { + temp.email = fieldValues.email ? "" : "This field is required."; + if (fieldValues.email) + temp.email = /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(fieldValues.email) + ? "" + : "Your email is incomplete."; + } + + if ("zipcode" in fieldValues) + temp.zipcode = fieldValues.zipcode ? "" : "This field is required."; + + setErrors({ + ...temp, + }); + }; + const handleInputValue = (e) => { + const { name, value } = e.target; + setFormValues({ + ...formValues, + [name]: value, + }); + validate({ + [name]: value, + }); + }; + const handleFormSubmit = async (e) => { + e.preventDefault(); + if (formIsValid()) { + setProcessing(true); + postTeamPayment({ totalAmount: calculatedAmount }) + .then(async (res) => { + const payload = await stripe.confirmCardPayment( + res.data.paymentIntentToken, + { + payment_method: { + card: elements.getElement(CardNumberElement), + billing_details: { + address: { + state: dropdownValue, + postal_code: formValues.zipcode, + }, + email: formValues.email, + }, + }, + } + ); + if (payload.error) { + setProcessing(false); + toastr.error("Payment failed", payload.error.message); + } else if (payload.paymentIntent.status === "succeeded") { + toastr.success("Payment is successful"); + setRequestLoading(true); + postTeamRequest(teamObject) + .then(() => { + setTimeout(() => { + dispatch(clearSearchedRoles()); + // Backend api create project has sync issue, so delay 2 seconds + navigate("/taas/myteams"); + }, 2000); + }) + .catch((err) => { + setRequestLoading(false); + toastr.error("Error Requesting Team", err.message); + }); + } + }) + .catch((err) => { + toastr.error("Error calculating amount", err.message); + }); + } + }; + + const formIsValid = (fieldValues = formValues) => { + const dropdown = dropdownValue === "" ? false : true; + const isValid = + fieldValues.email && + fieldValues.name && + fieldValues.zipcode && + dropdown && + Object.values(errors).every((x) => x === ""); + + return isValid; + }; + + const classes = useStyles(); + return ( + <> +
+ + + + Card Information + + + +
+ + +
+ + + + + + + + ); +}; + +export default PaymentForm; diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/PaymentForm/styles.module.scss b/src/routes/CreateNewTeam/pages/CreateTaasPayment/PaymentForm/styles.module.scss new file mode 100644 index 00000000..35dcbc10 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/PaymentForm/styles.module.scss @@ -0,0 +1,21 @@ +.button { + background: #137d60; + border-radius: 20px; + width: 258px; + height: 40px; + border: 0; + color: #ffffff; + text-transform: uppercase; + text-align: center; + display: block; + margin: 12px auto; +} + +.disabled { + background: #d4d4d4; +} + +.horizontal { + display: flex; + width: "100%"; +} diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/SelectField/countries.js b/src/routes/CreateNewTeam/pages/CreateTaasPayment/SelectField/countries.js new file mode 100644 index 00000000..c363a799 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/SelectField/countries.js @@ -0,0 +1,44 @@ +const countries = [ + { country: "Australia", code: "AU" }, + { country: "Austria", code: "AT" }, + { country: "Belgium", code: "BE" }, + { country: "Bulgaria", code: "BG" }, + { country: "Brazil ", code: "BR" }, + { country: "Canada", code: "CA" }, + { country: "Cyprus", code: "CY" }, + { country: "Czech Republic", code: "CZ" }, + { country: "Denmark", code: "DK" }, + { country: "Estonia", code: "EE" }, + { country: "Finland", code: "FI" }, + { country: "France", code: "FR" }, + { country: "Germany", code: "DE" }, + { country: "Greece", code: "GR" }, + { country: "Hong Kong", code: "HK" }, + { country: "Hungary", code: "HU" }, + { country: "India", code: "IN" }, + { country: "Ireland", code: "IE" }, + { country: "Italy", code: "IT" }, + { country: "Japan", code: "JP" }, + { country: "Latvia", code: "LV" }, + { country: "Lithuania", code: "LT" }, + { country: "Luxembourg", code: "LU" }, + { country: "Malaysia", code: "MY" }, + { country: "Malta", code: "MT" }, + { country: "Mexico ", code: "MX" }, + { country: "Netherlands", code: "NL" }, + { country: "New Zealand", code: "NZ" }, + { country: "Norway", code: "NO" }, + { country: "Poland", code: "PL" }, + { country: "Portugal", code: "PT" }, + { country: "Romania", code: "RO" }, + { country: "Singapore", code: "SG" }, + { country: "Slovakia", code: "SK" }, + { country: "Slovenia", code: "SI" }, + { country: "Spain", code: "ES" }, + { country: "Sweden", code: "SE" }, + { country: "Switzerland", code: "CH" }, + { country: "United Kingdom", code: "GB" }, + { country: "United States", code: "US" }, +]; + +export default countries; diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/SelectField/index.jsx b/src/routes/CreateNewTeam/pages/CreateTaasPayment/SelectField/index.jsx new file mode 100644 index 00000000..1c68a43a --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/SelectField/index.jsx @@ -0,0 +1,93 @@ +import React, { useState } from "react"; +import { TextField, MenuItem } from "@material-ui/core"; +import { makeStyles } from "@material-ui/core/styles"; +import Box from "@material-ui/core/Box"; + +const useStyles = makeStyles(() => ({ + label: { + color: "#AAAAAA", + fontFamily: "Roboto", + fontSize: "14px", + textAlign: "left", + "&.Mui-focused": { + color: "#137D60", + background: "#fffff", + }, + "&.Mui-error": { + color: "#EF476F", + }, + }, + menuItems: { + fontFamily: "Roboto", + fontSize: "14px", + textAlign: "left", + + "&.Mui-selected": { + background: "#137D60", + color: "#ffffff", + }, + "&:hover": { + background: "#137D60", + color: "#ffffff", + }, + }, +})); + +import countries from "./countries"; + +function SelectField({ dropdownValue, handleDropdown }) { + const [error, setError] = useState(false); + const handleChange = (event) => { + if (event.target.value === "") { + setError(true); + } else { + handleDropdown(event.target.value); + setError(false); + } + }; + + const classes = useStyles(); + return ( + + + {countries.map((country) => ( + + {country.country} + + ))} + + + ); +} + +export default SelectField; diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/StripeElement/StripeInput.js b/src/routes/CreateNewTeam/pages/CreateTaasPayment/StripeElement/StripeInput.js new file mode 100644 index 00000000..5a8fceee --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/StripeElement/StripeInput.js @@ -0,0 +1,40 @@ +import React from "react"; +import CreditCardIcon from "@material-ui/icons/CreditCard"; +import HelpOutlineIcon from "@material-ui/icons/HelpOutline"; +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles(() => ({ + icon: { + color: "#AAAAAA", + fontSize: "20px", + marginRight: "5px", + }, +})); + +function StripeInput(props) { + const { component: Component, inputRef, icon, ...other } = props; + const elementRef = React.useRef(); + + React.useImperativeHandle(inputRef, () => ({ + focus: () => elementRef.current.focus, + })); + + const classes = useStyles(); + return ( + <> + (elementRef.current = element)} + {...other} + /> + {icon === "card" ? ( + + ) : ( + <> + {icon === "cvc" ? : ""} + + )} + + ); +} + +export default StripeInput; diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/StripeElement/index.jsx b/src/routes/CreateNewTeam/pages/CreateTaasPayment/StripeElement/index.jsx new file mode 100644 index 00000000..79d92ee4 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/StripeElement/index.jsx @@ -0,0 +1,46 @@ +import React from "react"; +import TextField from "@material-ui/core/TextField"; +import Box from "@material-ui/core/Box"; +import StripeInput from "./StripeInput"; + +function StripeElement({ element, icon, width }) { + const [errorMessage, setErrorMessage] = React.useState(null); + function handleElementChange({ error, elementType }) { + if (error) { + if (elementType === "cardNumber") { + setErrorMessage("Credit card incomplete"); + } else setErrorMessage(error.message); + } else { + setErrorMessage(null); + } + } + + const hasError = errorMessage !== null; + + return ( + + + + ); +} + +export default StripeElement; diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/index.jsx b/src/routes/CreateNewTeam/pages/CreateTaasPayment/index.jsx new file mode 100644 index 00000000..7f76aa66 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/index.jsx @@ -0,0 +1,139 @@ +import React, { useState, useEffect } from "react"; +import { useSelector } from "react-redux"; +import { Elements } from "@stripe/react-stripe-js"; +import { loadStripe } from "@stripe/stripe-js"; +import { ThemeProvider } from "@material-ui/styles"; +import { toastr } from "react-redux-toastr"; + +import PaymentForm from "./PaymentForm"; +import PageHeader from "components/PageHeader"; +import { calculateAmount } from "services/teams"; +import Progress from "../../components/Progress"; +import theme from "./theme"; +import "./styles.module.scss"; + +const stripePromise = loadStripe(process.env.STRIPE_PUBLIC_KEY); +const CreateTassPayment = () => { + const [calculatedAmount, setCalculatedAmount] = useState(0); + const { addedRoles } = useSelector((state) => state.searchedRoles); + + // Backend has wrong test data so created dummy data for logic to work + const dummyRates = { + global: 50, + rate20Global: 20, + rate30Global: 20, + }; + + useEffect(() => { + const obj = { + numberOfResources: addedRoles.numberOfResources || 1, + rates: dummyRates.global, + durationWeeks: addedRoles.durationWeeks || 1, + }; + calculateAmount(obj) + .then((res) => { + setCalculatedAmount(res.data.totalAmount); + }) + .catch((err) => { + toastr.error("Error Requesting Team", err.message); + }); + }); + + const stages = [ + { name: "Input Job Description", completed: true }, + { name: "Search Member", completed: true }, + { name: "Overview of the Results", completed: true }, + { name: "Refundable Deposite Payment", isCurrent: true }, + ]; + + return ( +
+
+
+ Confirm your request
} + backTo="/taas/createnewteam/role/result" + /> +
+
+
+

summary

+
+ {addedRoles.map((role) => ( +
+
+ role +
+

{role.name}

+
    +
  • + {role.numberOfResources} x ${dummyRates.global}/ + Week +
  • +
  • {role.durationWeeks} Week Duration
  • +
  • + {role.hoursPerWeek + ? "Part-Time Availability" + : "Full-Time Availability"} +
  • +
+
+

+ ${role.numberOfResources * dummyRates.global} +

+
+
+
+ ))} +
+
+

Deposit & Refund Terms

+
    +
  • This is a refundable deposit payment.
  • +
  • + Topcoder will find you qualified candidates within 2 weeks, or + your money back. +
  • +
  • + If we find you talent that meets your needs, this deposit will + be credited towards your payment. +
  • +
  • + If we are only able to partially fill your talent order, we + will refund any portion we cannot fulfill. +
  • +
  • + Future payments can be processed on this credit card or you + can arrange invoicing. +
  • +
+
+
+

${calculatedAmount}

+

Total Deposit

+
+ + + + + +
+
+
+
+ + + + ); +}; + +export default CreateTassPayment; diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/styles.module.scss b/src/routes/CreateNewTeam/pages/CreateTaasPayment/styles.module.scss new file mode 100644 index 00000000..02102838 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/styles.module.scss @@ -0,0 +1,169 @@ +@import "styles/include"; + +.taas-payment { + display: flex; + flex-direction: row; + justify-content: center; + align-items: flex-start; + margin: 42px 35px; + .right-side { + display: flex; + flex-direction: column; + & > div:not(:first-child) { + margin-top: 16px; + } + } + input { + border: none !important; + box-shadow: none !important; + transition: none !important; + } + + .main-container { + @include rounded-card; + max-width: 746px; + width: 50vw; + margin-right: 30px; + background: #ffffff; + min-height: 730px; + display: flex; + justify-content: center; + + .page-title { + font-weight: 500; + } + + .content-container { + display: flex; + } + + .roles-container { + display: flex; + flex-direction: column; + } + + .summary { + margin-right: 15px; + + .scroll { + max-height: 300px; + overflow-y: auto; + } + + .role-container { + width: 358px; + margin-top: 14px; + + .roles { + display: flex; + justify-content: space-between; + margin-right: 15px; + } + + .image { + background-color: #ffffff; + border: 1px solid #d4d4d4; + border-radius: 5px; + width: 30px; + height: 30px; + } + + .title { + @include font-roboto; + font-size: 14px; + line-height: 17px; + text-align: left; + font-weight: 500; + margin-left: 10px; + } + + .details { + display: flex; + flex-direction: column; + @include font-roboto; + color: #555555; + font-size: 11px; + line-height: 15px; + text-align: left; + margin-left: 10px; + } + + .amount { + @include font-roboto; + font-size: 14px; + line-height: 17px; + text-align: right; + font-weight: 500; + margin-left: 10px; + margin-left: auto; + } + + .divider { + background-color: #e9e9e9; + width: 358px; + height: 1px; + margin-top: 14px; + } + } + } + + .heading { + @include font-barlow; + font-size: 16px; + font-weight: 600; + line-height: 20px; + text-transform: uppercase; + } + + .terms-title { + margin-top: 30px; + } + + .terms { + list-style-type: disc; + padding: 15px 0px 0px 25px; + color: #2a2a2a; + @include font-roboto; + font-size: 12px; + line-height: 18px; + width: 358px; + text-align: left; + } + + .payment { + background-color: #ffffff; + border: 2px solid #d4d4d4; + border-radius: 8px; + width: 298px; + min-height: 570px; + margin-left: 15px; + + hr { + background-color: #aaaaaa; + height: 1px; + margin: 20px 10px; + } + + .amount { + color: #1e94a3; + @include font-barlow-condensed; + font-size: 48px; + line-height: 50px; + text-align: center; + margin-top: 20px; + } + + .deposit { + color: #7f7f7f; + @include font-roboto; + font-size: 12px; + letter-spacing: 1px; + line-height: 16px; + text-align: center; + font-weight: 700; + text-transform: uppercase; + margin-top: 6px; + } + } + } +} diff --git a/src/routes/CreateNewTeam/pages/CreateTaasPayment/theme.js b/src/routes/CreateNewTeam/pages/CreateTaasPayment/theme.js new file mode 100644 index 00000000..d11d8cb4 --- /dev/null +++ b/src/routes/CreateNewTeam/pages/CreateTaasPayment/theme.js @@ -0,0 +1,17 @@ +import { createTheme } from "@material-ui/core/styles"; + +const theme = createTheme({ + palette: { + primary: { + main: "#229174", + }, + error: { + main: "#EF476F", + }, + background: { + default: "#ffffff", + }, + }, +}); + +export default theme; diff --git a/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx b/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx index 53244633..307a4a97 100644 --- a/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx +++ b/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx @@ -18,6 +18,7 @@ function InputJobDescription() { { name: "Input Job Description", isCurrent: true }, { name: "Search Member" }, { name: "Overview of the Results" }, + { name: "Refundable Deposite Payment" }, ]); const [jdString, setJdString] = useState(""); const [jobTitle, setJobTitle] = useState(""); diff --git a/src/routes/CreateNewTeam/pages/InputSkills/index.jsx b/src/routes/CreateNewTeam/pages/InputSkills/index.jsx index 516c057b..20ff6ede 100644 --- a/src/routes/CreateNewTeam/pages/InputSkills/index.jsx +++ b/src/routes/CreateNewTeam/pages/InputSkills/index.jsx @@ -21,6 +21,7 @@ function InputSkills() { { name: "Input Skills", isCurrent: true }, { name: "Search Member" }, { name: "Overview of the Results" }, + { name: "Refundable Deposite Payment" }, ]); const [selectedSkills, setSelectedSkills] = useState([]); const [popupSelectedSkills, setPopupSelectedSkills] = useState([]); diff --git a/src/routes/CreateNewTeam/pages/SelectRole/index.jsx b/src/routes/CreateNewTeam/pages/SelectRole/index.jsx index 88dcc6ff..54911650 100644 --- a/src/routes/CreateNewTeam/pages/SelectRole/index.jsx +++ b/src/routes/CreateNewTeam/pages/SelectRole/index.jsx @@ -25,6 +25,7 @@ function SelectRole() { { name: "Select a Role", isCurrent: true }, { name: "Search Member" }, { name: "Overview of the Results" }, + { name: "Refundable Deposite Payment" }, ]); const [selectedRoleId, setSelectedRoleId] = useState(null); const [roleDetailsModalOpen, setRoleDetailsModalOpen] = useState(false); diff --git a/src/routes/CreateNewTeam/reducers/index.js b/src/routes/CreateNewTeam/reducers/index.js index 3e14ceac..5212d05f 100644 --- a/src/routes/CreateNewTeam/reducers/index.js +++ b/src/routes/CreateNewTeam/reducers/index.js @@ -1,6 +1,7 @@ /** * Reducer for CreateNewTeam flow */ +import _ from "lodash"; import { ACTION_TYPE } from "constants"; const loadState = () => { @@ -9,6 +10,7 @@ const loadState = () => { addedRoles: [], matchingRole: undefined, isLoading: false, + teamObject: undefined, }; try { const state = localStorage.getItem("rolesState"); @@ -40,6 +42,12 @@ const reducer = (state = initialState, action) => { addedRoles: [], }; + case ACTION_TYPE.ADD_TEAM_OBJECT: + return { + ...state, + teamObject: action.payload, + }; + case ACTION_TYPE.ADD_MATCHING_ROLE: return { ...state, diff --git a/src/services/teams.js b/src/services/teams.js index b8b4200c..8bb646e7 100644 --- a/src/services/teams.js +++ b/src/services/teams.js @@ -237,3 +237,22 @@ export const postTeamRequest = (teamObject) => { const url = `${config.API.V5}/taas-teams/submitTeamRequest`; return axios.post(url, teamObject); }; + +/** + * + * @param {Object} amountObject object containing details for calculating total amount + * @returns {Promise} object containing calculated amount + */ +export const calculateAmount = (amountObject) => { + const url = `${config.API.V5}/taas-teams/calculateAmount`; + return axios.post(url, amountObject); +}; +/** + * + * @param {Object} paymentObject object containing total amount + * @returns {Promise} object containing paymentInitiation token obtained from stripe + */ +export const postTeamPayment = (paymentObject) => { + const url = `${config.API.V5}/taas-teams/createPayment`; + return axios.post(url, paymentObject); +}; diff --git a/webpack.config.js b/webpack.config.js index 45cc538f..3d543b5f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -80,6 +80,7 @@ module.exports = (webpackConfigEnv) => { new webpack.DefinePlugin({ "process.env": { APPENV: JSON.stringify(process.env.APPENV), + STRIPE_PUBLIC_KEY: JSON.stringify(process.env.STRIPE_PUBLIC_KEY), }, }), ],