diff --git a/Apply-For-Me-UI/package-lock.json b/Apply-For-Me-UI/package-lock.json index 3bdbfa16..d22cb184 100644 --- a/Apply-For-Me-UI/package-lock.json +++ b/Apply-For-Me-UI/package-lock.json @@ -17,6 +17,7 @@ "atatus-spa": "^4.5.0", "axios": "^1.2.0", "formik": "^2.2.9", + "framer-motion": "^8.4.3", "hamburger-react": "^2.5.0", "jwt-decode": "^3.1.2", "react": "^18.2.0", @@ -2173,6 +2174,21 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -3017,6 +3033,64 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@motionone/animation": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", + "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", + "dependencies": { + "@motionone/easing": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.15.5", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.15.5.tgz", + "integrity": "sha512-Xc5avlgyh3xukU9tydh9+8mB8+2zAq+WlLsC3eEIp7Ax7DnXgY7Bj/iv0a4X2R9z9ZFZiaXK3BO0xMYHKbAAdA==", + "dependencies": { + "@motionone/animation": "^10.15.1", + "@motionone/generators": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", + "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", + "dependencies": { + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", + "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", + "dependencies": { + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", + "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" + }, + "node_modules/@motionone/utils": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", + "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", + "dependencies": { + "@motionone/types": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -9479,6 +9553,23 @@ "node": ">=0.10.0" } }, + "node_modules/framer-motion": { + "version": "8.4.3", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-8.4.3.tgz", + "integrity": "sha512-UMfJ8hEOlIObdJgI+U/VgaSSKY+W9/E0YtnFHPDsIE9rNPglaFZ+oycB0gj8ERuRBInGaIgNCFsil8iaJHZFgA==", + "dependencies": { + "@motionone/dom": "^10.15.3", + "hey-listen": "^1.0.8", + "tslib": "^2.4.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -9951,6 +10042,11 @@ "he": "bin/he" } }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -22835,6 +22931,21 @@ "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", "requires": {} }, + "@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "requires": { + "@emotion/memoize": "0.7.4" + } + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -23460,6 +23571,64 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "@motionone/animation": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", + "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", + "requires": { + "@motionone/easing": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "@motionone/dom": { + "version": "10.15.5", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.15.5.tgz", + "integrity": "sha512-Xc5avlgyh3xukU9tydh9+8mB8+2zAq+WlLsC3eEIp7Ax7DnXgY7Bj/iv0a4X2R9z9ZFZiaXK3BO0xMYHKbAAdA==", + "requires": { + "@motionone/animation": "^10.15.1", + "@motionone/generators": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "@motionone/easing": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", + "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", + "requires": { + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "@motionone/generators": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", + "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", + "requires": { + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "@motionone/types": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", + "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" + }, + "@motionone/utils": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", + "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", + "requires": { + "@motionone/types": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, "@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -28320,6 +28489,17 @@ "map-cache": "^0.2.2" } }, + "framer-motion": { + "version": "8.4.3", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-8.4.3.tgz", + "integrity": "sha512-UMfJ8hEOlIObdJgI+U/VgaSSKY+W9/E0YtnFHPDsIE9rNPglaFZ+oycB0gj8ERuRBInGaIgNCFsil8iaJHZFgA==", + "requires": { + "@emotion/is-prop-valid": "^0.8.2", + "@motionone/dom": "^10.15.3", + "hey-listen": "^1.0.8", + "tslib": "^2.4.0" + } + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -28660,6 +28840,11 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", diff --git a/Apply-For-Me-UI/package.json b/Apply-For-Me-UI/package.json index b8f4b5c1..fde56f57 100644 --- a/Apply-For-Me-UI/package.json +++ b/Apply-For-Me-UI/package.json @@ -12,6 +12,7 @@ "atatus-spa": "^4.5.0", "axios": "^1.2.0", "formik": "^2.2.9", + "framer-motion": "^8.4.3", "hamburger-react": "^2.5.0", "jwt-decode": "^3.1.2", "react": "^18.2.0", diff --git a/Apply-For-Me-UI/src/App.jsx b/Apply-For-Me-UI/src/App.jsx index ad9a32c8..50e5643f 100644 --- a/Apply-For-Me-UI/src/App.jsx +++ b/Apply-For-Me-UI/src/App.jsx @@ -38,9 +38,9 @@ import ApplicantDetails from "./pages/admin_dashboard/components/applicant_detai import ApplicationForm from "./pages/admin_dashboard/components/application_form/ApplicationForm"; import DashboardHome from "./pages/admin_dashboard/components/dashboard_home/DashboardHome"; import { pricingPage } from "pages/pricing_plan/pricingData"; -import { formData } from "pages/checkout/checkoutData"; +// import { formData } from "pages/checkout/checkoutData"; import Pricing from "./pages/pricing_plan/Pricing"; -import Checkout from "pages/checkout/Checkout"; +// import Checkout from "pages/checkout/Checkout"; import ProtectedRoute from "ProtectedRoute"; //UserDashboard import NoProfile from "./pages/dashboard_profile/NoProfile/NoProfile"; @@ -63,7 +63,7 @@ import Verification from "pages/authentication-pages/Verification"; import Password from "pages/authentication-pages/Password"; import NewPass from "pages/authentication-pages/NewPass"; import Registration from "pages/authentication-pages/Registration"; -import {RRAdminProfilePage } from "pages/RR_admin_profile/RR_admin_profile"; +import { RRAdminProfilePage } from "pages/RR_admin_profile/RR_admin_profile"; import { useEffect } from "react"; import SignIn from "pages/RR_recuiters_page/Sign_In"; @@ -77,6 +77,9 @@ import * as atatus from "atatus-spa"; import ReactGA from "react-ga4"; import { CreateRecruiter } from "pages/createRecruiter/create_view"; import { SuperApplicantsPage } from "pages/users_page/user_page_applicants"; +import { PaystackPage } from "pages/paystack/paystack"; + +import PaymentVerification from "pages/paystack/verification/Verification"; atatus.config("c626faaef503411ea6216d7b6112de1c").install(); @@ -112,6 +115,11 @@ function App() { } /> } /> } /> + } + /> } + path="/checkout/:planName/:paymentInterval/:price" + // element={} + element={} /> } /> @@ -226,7 +235,7 @@ function App() { {/* User Dashboard Profile */} } /> { return ( @@ -26,16 +27,29 @@ const Footer = () => {

diff --git a/Apply-For-Me-UI/src/components/nav/Nav.jsx b/Apply-For-Me-UI/src/components/nav/Nav.jsx index dd17242b..7bcd34c7 100644 --- a/Apply-For-Me-UI/src/components/nav/Nav.jsx +++ b/Apply-For-Me-UI/src/components/nav/Nav.jsx @@ -9,7 +9,7 @@ import LightButton from "../buttons/light_button/LightButton"; import { useDispatch, useSelector } from "react-redux"; import { userInfo } from "store/slice/UserSlice"; -const Nav = () => { +const Nav = ({setSeeMore}) => { const initState = { "about": false, "price": false, @@ -67,7 +67,7 @@ const Nav = () => {
  • - + setSeeMore(false)}> Pricing plan
  • @@ -165,7 +165,7 @@ const Nav = () => {
  • navigate("/about")}> About us
  • -
  • navigate("/pricing")}> +
  • { setSeeMore(false); navigate("/pricing") }}> Pricing plan
  • navigate("/faqs")}> diff --git a/Apply-For-Me-UI/src/components/spinner/MoonLoader.jsx b/Apply-For-Me-UI/src/components/spinner/MoonLoader.jsx new file mode 100644 index 00000000..1adf05d2 --- /dev/null +++ b/Apply-For-Me-UI/src/components/spinner/MoonLoader.jsx @@ -0,0 +1,24 @@ +import React from "react"; +import { useState } from "react"; +import MoonLoader from "react-spinners/MoonLoader"; +import classes from "./Spinner.module.css"; +const Spinner = () => { + let [color] = useState("#2E3192"); + + return ( +
    +
    + +
    +

    verifying payment...

    +
    +
    + ); +}; + +export default Spinner; diff --git a/Apply-For-Me-UI/src/components/spinner/MoonLoader.module.css b/Apply-For-Me-UI/src/components/spinner/MoonLoader.module.css new file mode 100644 index 00000000..c383e654 --- /dev/null +++ b/Apply-For-Me-UI/src/components/spinner/MoonLoader.module.css @@ -0,0 +1,19 @@ +.spinner_container { + position: fixed; + left: 0%; + right: 0%; + opacity: 0.9; + bottom: 0%; + z-index: 1000000; + height: 100vh; + display: flex; + align-items: center; + justify-content: center; + background-color: gray; +} + +.spinner_inner { + display: flex; + flex-direction: column; + align-items: center; +} \ No newline at end of file diff --git a/Apply-For-Me-UI/src/components/spinner/PulseLoader.jsx b/Apply-For-Me-UI/src/components/spinner/PulseLoader.jsx index c14fd667..b390d42d 100644 --- a/Apply-For-Me-UI/src/components/spinner/PulseLoader.jsx +++ b/Apply-For-Me-UI/src/components/spinner/PulseLoader.jsx @@ -1,13 +1,13 @@ import React from "react"; import { useState } from "react"; -import PulseLoader from "react-spinners/PulseLoader"; +import BarLoader from "react-spinners/BarLoader"; import classes from "./Spinner.module.css"; const Spinner = () => { let [color] = useState("#2E3192"); return (
    - { let [color] = useState("#2E3192"); return (
    - diff --git a/Apply-For-Me-UI/src/pages/RR_Dashboard/styles/Applications.module.css b/Apply-For-Me-UI/src/pages/RR_Dashboard/styles/Applications.module.css index 3b64d182..99db8f82 100644 --- a/Apply-For-Me-UI/src/pages/RR_Dashboard/styles/Applications.module.css +++ b/Apply-For-Me-UI/src/pages/RR_Dashboard/styles/Applications.module.css @@ -9,7 +9,35 @@ padding: 0rem 1rem; border-radius: 5px; } +.entry_mappping { + width:100%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid #F2F2F2; + padding: 1rem 0; + +} +h5 { + color: #52515B; +} +.entry_maps { + width: 100%; + text-align: left; +} +.entry_map { + width: 100%; + text-align: left; + color: #52515B !important; +} +.entry_map > span { + color: #52515B; +} +.entry_mapt { + text-align: right; +} .greeting_text>h1 { font-size: 1rem; font-weight: 500; @@ -113,7 +141,10 @@ .stats_item { font-weight: 300; - width:25%; + width:100%; + background-color: red; + display: flex; + } .stats_details_view_button { @@ -122,6 +153,7 @@ } .stats_row { + background-color: yellowgreen; border-bottom: 1px solid rgba(230, 230, 233, 1); display: flex; align-items: center; @@ -142,7 +174,12 @@ .desktop_only { display: block; } - +.greeting_text { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; +} @media screen and (min-width: 768px) { .rrd_applications_wrapper { padding: 2rem 2.5rem; @@ -151,6 +188,9 @@ .desktop_only { display: block; } + .tab_option { + display: none; + } .greeting_text>h1 { font-size: 1.5rem; @@ -188,7 +228,7 @@ .stats_row { border-bottom: 1px solid rgba(230, 230, 233, 1); display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-columns: auto auto auto auto auto; gap: 4%; list-style-type: none; padding: 32px 0px 16px; @@ -215,6 +255,10 @@ .rrd_applications_wrapper { padding: 2rem 7rem; } + + .entry_mappping > h5 { + font-size: 1.4rem !important; + } .greeting_text>p, .stat_text, @@ -233,7 +277,7 @@ } .stats_row { - grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-columns: auto auto auto auto auto; gap: 3.5%; } @@ -260,4 +304,17 @@ .stats_details_view_button { font-size: 12px; } + .mobile_option { + display: none; + } + .entry_mappping > h5 { + font-size: 1rem !important; + } + .mobile_opt { + display: flex; + width: 35%; + flex-wrap: wrap; + } + + } \ No newline at end of file diff --git a/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.jsx b/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.jsx index 7b5680df..a8c03770 100644 --- a/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.jsx +++ b/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.jsx @@ -79,7 +79,7 @@ const ApplicationDetails = () => {

    Job Information

    -
    +

    Name

    {details?.profileTitle}

    @@ -97,8 +97,8 @@ const ApplicationDetails = () => {

    {details?.jobSeniority}

    -

    Experience

    -

    {details?.yearsOfExperience}

    +

    Industry

    +

    Tech

    Salary Expectation

    @@ -108,6 +108,10 @@ const ApplicationDetails = () => {

    Employment Type

    {details?.employmentType}

    +
    +

    Remaining Aplication

    +

    52

    +
    diff --git a/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.module.css b/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.module.css index 5272f531..aa283dc6 100644 --- a/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.module.css +++ b/Apply-For-Me-UI/src/pages/admin_dashboard/components/applicant_details/ApplicantDetails.module.css @@ -85,6 +85,7 @@ .job_information>div { display: flex; + flex-flow: row wrap; gap: 35px; } @@ -128,6 +129,8 @@ .job_information>div { gap: 27px; + width: 100%; + justify-content: space-between; } } @@ -157,7 +160,10 @@ } .job_information>div { - justify-content: space-between; + width: 100%; + display: flex; + align-items: left; + justify-content: flex-start; } .job_information h2 { diff --git a/Apply-For-Me-UI/src/pages/admin_dashboard/components/application_list/ApplicationList.jsx b/Apply-For-Me-UI/src/pages/admin_dashboard/components/application_list/ApplicationList.jsx index d42d937a..e0926da1 100644 --- a/Apply-For-Me-UI/src/pages/admin_dashboard/components/application_list/ApplicationList.jsx +++ b/Apply-For-Me-UI/src/pages/admin_dashboard/components/application_list/ApplicationList.jsx @@ -1,92 +1,93 @@ import classes from "../../../RR_Dashboard/styles/Applications.module.css"; import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; -import axios from 'axios'; +import '../../../RR_Dashboard/styles/Applications.module.css'; +import axios from "axios"; import { useCallback } from "react"; - +import Spinner from "components/spinner/Spinner"; const ApplicationList = () => { const [listArray, setListArray] = useState(); + const [isLoading, setIsLoading] = useState(true); + const token = localStorage.getItem("tokenHngKey"); - const getApplicationDetail = useCallback( async () => { - try { - const response = await axios.get( - "https://api.applyforme.hng.tech/api/v1/professional-profile/entries/all", - { - headers: { - "Authorization": `Bearer ${token}` - } - } - ); - setListArray(response.data.content); - } catch (err) { - console.log(err.response?.data); - } - },[token]); - useEffect(() => { - getApplicationDetail (); - }, [ getApplicationDetail]); + const getApplicationDetail = useCallback(async () => { + try { + const response = await axios.get( + "https://api.applyforme.hng.tech/api/v1/professional-profile/entries/all", + { + headers: { + "Authorization": `Bearer ${token}` + } + } + ); + setListArray(response.data.content); + setIsLoading(false); + } catch (err) { + console.log(err.response?.data); + } + }, [token]); + useEffect(() => { + getApplicationDetail(); + }, [getApplicationDetail]); + + if (isLoading) { + return ; + } return ( // Application stats Table
    - {/* Heading Row */} -
      -
    • - Name -
    • -
    • - Salary -
    • -
    • - Type -
    • -
    • - Details -
    • -
    - - - { - listArray?.length!== 0 ? ( - listArray?.map((entry, i) => { - return ( - // Entry Row -
      -
    • - {entry.profileTitle} -
    • -
    • - {entry.salaryRange} -
    • -
    • - {entry.preferredJobLocationType} -
    • -
    • - - view +
      +
      Name
      +
      UserPlan
      +
      Job Title
      +
      Salary
      +
      Type
      +
      Details
      +
      + {listArray?.length !== 0 ? ( + listArray?.map((entry, i) => { + return ( +
      +
      +
      + + {entry.professional.member.firstName } + + + {entry.professional.member.lastName } + +
      +
      Basic Plan
      +
      {entry.profileTitle}
      +
      {entry.salaryRange}
      +
      {entry.preferredJobLocationType}
      +
      + + view -
    • -
    - ); - }) - ):

    No applications have being made

    - } +
    +
    +
  • + ); + }) + ) : ( +

    + No applications have being made +

    + )} ); }; diff --git a/Apply-For-Me-UI/src/pages/admin_dashboard/components/dashboard_home/DashboardHome.jsx b/Apply-For-Me-UI/src/pages/admin_dashboard/components/dashboard_home/DashboardHome.jsx index 20fe2b79..20dc46bd 100644 --- a/Apply-For-Me-UI/src/pages/admin_dashboard/components/dashboard_home/DashboardHome.jsx +++ b/Apply-For-Me-UI/src/pages/admin_dashboard/components/dashboard_home/DashboardHome.jsx @@ -45,7 +45,7 @@ const DashboardHome = () => { {/* Greetings */}

    Good evening Admin, 👋🏼

    -

    Here is how you are fairing today

    +

    How are you fairing today

    @@ -79,7 +79,7 @@ const DashboardHome = () => {

    - New Submissions + New Applications(23)

    )} -
    +
    -
    + -
    +
    - + ); }; diff --git a/Apply-For-Me-UI/src/pages/landing_page/Hero.module.css b/Apply-For-Me-UI/src/pages/landing_page/Hero.module.css index cc1026ca..d51d80c7 100644 --- a/Apply-For-Me-UI/src/pages/landing_page/Hero.module.css +++ b/Apply-For-Me-UI/src/pages/landing_page/Hero.module.css @@ -425,7 +425,7 @@ input[type=file]{ width: 90%; margin: auto; display: flex; - align-items: center; + /* align-items: center; */ } .FAQ_content div { @@ -444,6 +444,7 @@ input[type=file]{ .FAQ_content div .text { width: 80%; margin-right: auto; + margin-top: 3rem; } .FAQ_content div .text p { @@ -453,12 +454,12 @@ input[type=file]{ } -.FAQ_content div h3 { +/* .FAQ_content div h3 { font-weight: 500; width: 100%; color: #2E3192; font-size: 40px; -} +} */ .FAQ_content div ul li { list-style: none; @@ -572,7 +573,7 @@ input[type=file]{ } .FAQ_content div h3 { - font-size: 1.5rem; + font-size: 1.2rem; } .learn_content .bottom { padding: 80px 40px; @@ -773,6 +774,7 @@ input[type=file]{ .FAQ_content div .text { width: 100%; + margin-top: 0; } .FAQ_content div ul { diff --git a/Apply-For-Me-UI/src/pages/landing_page/LearnMore.jsx b/Apply-For-Me-UI/src/pages/landing_page/LearnMore.jsx index e897f29e..3aae7283 100644 --- a/Apply-For-Me-UI/src/pages/landing_page/LearnMore.jsx +++ b/Apply-For-Me-UI/src/pages/landing_page/LearnMore.jsx @@ -2,10 +2,15 @@ import React from 'react' import { useNavigate } from 'react-router-dom'; import classes from "./Hero.module.css"; +import { motion } from "framer-motion"; const LearnMore = () => { const navigate = useNavigate(); return ( -
    +
    @@ -76,7 +81,7 @@ const LearnMore = () => {
    -
    + ); }; diff --git a/Apply-For-Me-UI/src/pages/landing_page/Pricing.jsx b/Apply-For-Me-UI/src/pages/landing_page/Pricing.jsx index 27154005..6744a098 100644 --- a/Apply-For-Me-UI/src/pages/landing_page/Pricing.jsx +++ b/Apply-For-Me-UI/src/pages/landing_page/Pricing.jsx @@ -2,11 +2,15 @@ import React from "react"; import { useNavigate } from "react-router-dom"; import classes from "./Hero.module.css"; - +import { motion } from "framer-motion"; const Pricing = () => { const navigate = useNavigate(); return ( -
    +
    { lineHeight: "30px" }} > - As part of the basic plan, we send 15 + As part of the basic plan, we send 60 job applications every month to various employers who are searching for your skill-set @@ -64,7 +68,7 @@ const Pricing = () => { lineHeight: "30px" }} > - You can create up to 5 job profiles of + You can create up to 4 job profiles of different qualifications in search of various roles within an organisation @@ -76,9 +80,7 @@ const Pricing = () => { alt="object not found" />
    -

    - CV Review -

    +

    CV Review

    {
    - Basic plan + Free plan - $15.99 + $0 { src="https://res.cloudinary.com/hamskid/image/upload/v1669939094/Vector_12_mmv9yq.png" alt="object not found" /> - up to 15 applications per month + Up to 5 job applications per month + + + object not found + Can create up to 1 job profiles object not found - can create upto 5 job profiles + Access to 2 Keywords per job profile object not found - Access to 2 customer care session on CV review + Access to 1 cover letter templates
    @@ -147,7 +156,7 @@ const Pricing = () => {
    -
    +
    ); }; diff --git a/Apply-For-Me-UI/src/pages/landing_page/Reviews.jsx b/Apply-For-Me-UI/src/pages/landing_page/Reviews.jsx index 8126092b..093e5dd3 100644 --- a/Apply-For-Me-UI/src/pages/landing_page/Reviews.jsx +++ b/Apply-For-Me-UI/src/pages/landing_page/Reviews.jsx @@ -2,10 +2,13 @@ import React from "react"; import classes from "./Hero.module.css"; import Avatar from "../../assets/images/Avatar1.png"; import Avatar2 from "../../assets/images/Avatar2.png"; - +import { motion } from "framer-motion"; const Reviews = () => { return ( -
    +
    {
    -
    + ); }; diff --git a/Apply-For-Me-UI/src/pages/landing_page/Service.jsx b/Apply-For-Me-UI/src/pages/landing_page/Service.jsx index cf1ef5d8..f49d2f40 100644 --- a/Apply-For-Me-UI/src/pages/landing_page/Service.jsx +++ b/Apply-For-Me-UI/src/pages/landing_page/Service.jsx @@ -1,8 +1,13 @@ import React from 'react' import classes from "./Hero.module.css" +import { motion } from "framer-motion"; const Service = () => { return ( -
    +
    {

    -
    + ); }; diff --git a/Apply-For-Me-UI/src/pages/landing_page/question.jsx b/Apply-For-Me-UI/src/pages/landing_page/question.jsx new file mode 100644 index 00000000..17a0c81d --- /dev/null +++ b/Apply-For-Me-UI/src/pages/landing_page/question.jsx @@ -0,0 +1,51 @@ +import React, { useState } from "react"; +import { Link } from "react-router-dom"; +import { motion } from "framer-motion"; + +import styles from "./question.module.css"; + +//Component that manages it's own state onclick +export const Question = ({ subQuestion, answer, subIcon,month }) => { + const [text, setText] = useState(false); + return ( +
    setText(!text)}> +
    +

    {subQuestion}

    + object not found +
    + { + text ? ( + +

    {answer}

    +
    {month}
    + Learn more +
    + ): + ( + +

    {answer}

    +
    {month}
    + Learn more +
    + ) + } +
    + ); +}; + diff --git a/Apply-For-Me-UI/src/pages/landing_page/question.module.css b/Apply-For-Me-UI/src/pages/landing_page/question.module.css new file mode 100644 index 00000000..f99f42c1 --- /dev/null +++ b/Apply-For-Me-UI/src/pages/landing_page/question.module.css @@ -0,0 +1,138 @@ +.faqWrapper { + width: min(90%, 85rem); + margin-inline: auto; +} + +.faqmain { + margin-bottom: 2.5rem; +} + +.faqheading { + line-height: 1.4; + margin-bottom: 1rem; + color: #4347B2; +} + +.faqText { + margin-bottom: 1rem; + font-size: 0.87rem; + color: #1b1b1b; + font-weight: 300; +} + +.content__box { + /*border: 2px solid red;*/ + + border-bottom: 1px solid #9194a1; + cursor: pointer; + padding: 1rem 0 0.5rem; + width: 100%; +} +.faqlist{ + font-size: 16px; +} +.contentbox__question { + display: flex; + justify-content: space-between; + align-items: center; +} +.innerText{ + padding-right:0.5rem; +} + +.minheading { + font-weight: 400; + margin-bottom: 1rem; + font-size: 1rem; +} + +.faqicon { + margin-top: -0.4rem; + transition: all 0.3s ease-in; +} + +.faqicon__active { + transform: rotate(-180deg); +} +@media only screen and (max-width:899px){ + .majorPlan { + flex-direction: column; + margin:0 auto; + justify-content: center; + align-items: center; + } + .card{ + width: fit-content; + } +} +@media screen and (max-width: 584px) { + .toggle { + display: none; + } +} + +/*BreakPoints*/ +@media only screen and (min-width: 900px) { + + .mainheading { + margin-bottom: 1.625rem; + font-size: 2.5vmax; + } + + .primaryText { + font-size: 2vmax; + } + + .majorPlan { + display: flex; + padding: 7rem 0 ; + flex-direction: row; + justify-content: space-around; + gap: 3vmax; + padding: 7rem 0; + position: relative; + /*grid-template-rows: auto;*/ + /*justify-content: space-between;*/ + } + + .majorPlan > .card:nth-child(2) { + transform: scale(1.1, 1.25); + } + + .majorPlan > .card:not(:nth-child(2)) .statusWrapper { + margin-bottom: 2rem; + } + + .status { + gap: 0.5rem; + } + + .status__text { + font-size: 1vmax; + } + + .secondaryHeading { + font-size: 2vmax; + } + + .secondaryText { + font-size: 1.5vmax; + } + + .faqWrapper { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 3.5vmax; + } + + .faqText { + font-size: 1rem; + margin-bottom: 1rem; + max-width: 35ch; + } + + .faqheading { + font-size: 2.3vmax; + max-width: 15ch; + } +} \ No newline at end of file diff --git a/Apply-For-Me-UI/src/pages/paystack/paystack.css b/Apply-For-Me-UI/src/pages/paystack/paystack.css new file mode 100644 index 00000000..7a1102b6 --- /dev/null +++ b/Apply-For-Me-UI/src/pages/paystack/paystack.css @@ -0,0 +1,99 @@ +.pay_header { + display: flex; + justify-content: space-between; + width: 100%; + padding: 1.5rem 3rem; + background-color: #f9f9ff; +} +.header_cred_wrapper { + display: flex; + align-items: center; +} +.cred_wrapper { + margin-left: 1rem; +} +.header_credName { + font-weight: 400; + font-size: 28px; + line-height: 150%; + color: #222226; +} +.confirm_text { + font-weight: 500; + font-size: 28px; + line-height: 120%; + color: #171646; + margin: 2rem 0; +} +.pay_input { + background: #edf5fd; + font-weight: 400; + padding: 1rem; + font-size: 16px; + color: #171646; + height: 56px; + border: 2px solid #52515b; + border-radius: 8px; + width: 100%; +} +.pay_form_wrapper { + width: 45%; + margin: 2rem auto 6rem; +} +.inputDiv_wrapper { + display: flex; + flex-direction: column; + margin-bottom: 1rem; +} +.form_label { + margin-bottom: 1rem; + font-weight: 500; + font-size: 20px; + line-height: 120%; + color: #222226; +} +.submit_btn { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 16px 32px; + gap: 8px; + width: 100%; + height: 62px; + background: #2e3192; + border-radius: 8px; + color: white; +} +.paystack_footer { + margin: 2rem auto; + width: fit-content; +} +.form_wrapper_bg { + background: #edf5fd; + padding-bottom: 2rem; + margin-bottom: 0; +} +@media only screen and (max-width: 600px) { + .pay_form_wrapper { + width: 90%; + } +} +@media only screen and (max-width: 425px) { + .pay_header { + padding: 1rem 0.5rem; + } + .header_credName { + font-size: 18px; + } + .afm { + width: 80%; + } + .avatar { + width: 70%; + } + .cred_wrapper { + margin-left: 0rem; + margin-bottom: -1rem; + } +} diff --git a/Apply-For-Me-UI/src/pages/paystack/paystack.jsx b/Apply-For-Me-UI/src/pages/paystack/paystack.jsx new file mode 100644 index 00000000..0b25e15a --- /dev/null +++ b/Apply-For-Me-UI/src/pages/paystack/paystack.jsx @@ -0,0 +1,169 @@ +import "./paystack.css"; +import jwt_decode from "jwt-decode"; +import { useParams } from "react-router-dom"; +import Spinner from "components/spinner/PulseLoader"; +import { useState } from "react"; +import axios from "axios"; +import { toast, ToastContainer } from "react-toastify"; + +export const PaystackPage = () => { + const [loading, setLoading] = useState(false); + let decoded = jwt_decode(localStorage?.getItem("tokenHngKey")); + const { price, planName, paymentInterval } = useParams(); + const channels = ["card", "bank"]; + const currency = "NGN"; + const token = localStorage.getItem("tokenHngKey"); + + const createPlan = async(planName,paymentInterval)=>{ + setLoading(true); + try{ + const response = await axios + .post("https://api.applyforme.hng.tech/api/v1/paystack/createplan", + { + "name": planName.toLowerCase(), + "interval": paymentInterval, + "amount": Math.round((price*451.60) *100), + }, + { + headers: { + "Authorization": `Bearer ${token}` + } + } + ) + if(response.data.status === true){ + let paymentCode = response?.data?.data?.plan_code + let paymentPlan = response?.data?.data?.name + initializePlan(decoded.emailAddress,currency,paymentCode,channels); + localStorage.setItem("paymentPlan", paymentPlan); + } + }catch(err){ + toast.error(err?.response?.data?.message); + setLoading(false); + } + } + + const initializePlan = async(email,currency,paymentCode,channels)=>{ + try{ + const response = await axios + .post("https://api.applyforme.hng.tech/api/v1/paystack/initializepayment", + { + "amount": Math.round((price*451.60)*100), + "email":email, + "currency": currency, + "plan": paymentCode, + "channels":channels + }, + { + headers: { + "Authorization": `Bearer ${token}` + } + } + ) + if(response.data.status === true){ + let paymentRef = response?.data?.data?.reference; + localStorage.setItem("paymentRef", paymentRef); + let AuthorizationUrl = response?.data?.data?.authorization_url + console.log(paymentRef); + window.location.href = AuthorizationUrl; + } + }catch(err){ + toast.error(err?.response?.data?.message); + setLoading(false); + } + } + + const handleSubmit = (e)=>{ + e.preventDefault(); + createPlan(planName,paymentInterval); + } + + if (loading) { + return ; + } + return ( + <> + +
    +
    +
    + object not found +
    +
    + + object not found + + +

    {decoded?.fullName}

    +
    +
    +
    +
    +
    +
    + object not found window.history.back()} + /> +
    +

    + Please Confirm your payment information to continue +

    +
    + + +
    +
    + + +
    +
    + + +
    + +
    +
    + object not found +
    +
    +
    + + + + ); +}; diff --git a/Apply-For-Me-UI/src/pages/paystack/verification/Verification.jsx b/Apply-For-Me-UI/src/pages/paystack/verification/Verification.jsx new file mode 100644 index 00000000..09715670 --- /dev/null +++ b/Apply-For-Me-UI/src/pages/paystack/verification/Verification.jsx @@ -0,0 +1,93 @@ +import { useCallback, useEffect, useState} from "react"; +import axios from "axios"; +import Spinner from "components/spinner/MoonLoader"; +import {FaRegTimesCircle,FaRegCheckCircle} from 'react-icons/fa'; +import "./verification.css"; +import { useNavigate } from "react-router-dom"; + +const PaymentVerification = () => { + const navigate = useNavigate(); + const baseURL = "https://api.applyforme.hng.tech"; + const token = localStorage?.getItem("tokenHngKey"); + const reference = localStorage?.getItem("paymentRef"); + const plan = localStorage?.getItem("paymentPlan"); + const [verificationDetails, setVerificationDetails] = useState({ + status:null, + message:null + }); + const [status, setStatus] = useState(false); + const [isLoading, setisLoading] = useState(true); + + const verifyPayment = useCallback(async () => { + try { + const response = await axios.get( + `${baseURL}/api/v1/paystack/verifypayment/${reference}/${plan}`, + { + params:{ + 'reference':reference, + 'plan':plan + }, + headers: { + "Authorization": `Bearer ${token}` + } + } + ); + console.log(response?.data); + setVerificationDetails({ + status:response?.data?.status, + message:response?.data.message + }); + setStatus(true); + setisLoading(false); + setTimeout(()=>{ + navigate("/pricing"); + },5000); + } catch (err){ + console.log(err); + setVerificationDetails((prev)=>{ + return {...prev, message: err.response?.data.message}; + }) + + setisLoading(false); + setTimeout(()=>{ + navigate("/pricing"); + },5000); + } + },[plan,reference,token,navigate]) + + useEffect(() => { + verifyPayment(); + console.log("Working"); + }, [ verifyPayment]); + + if(isLoading){ + return( +
    + {isLoading && } +
    + ) + } + return ( +
    + { + verificationDetails.status === true && +
    + +

    Verification successful!

    +

    {verificationDetails.message}

    +
    + } + { + (verificationDetails.status === false || !status) && +
    + +

    Verification Failed!

    +

    {verificationDetails.message}

    +
    + + } +
    + ) +}; + +export default PaymentVerification; diff --git a/Apply-For-Me-UI/src/pages/paystack/verification/verification.css b/Apply-For-Me-UI/src/pages/paystack/verification/verification.css new file mode 100644 index 00000000..03d2103d --- /dev/null +++ b/Apply-For-Me-UI/src/pages/paystack/verification/verification.css @@ -0,0 +1,30 @@ +.message_container{ + display:flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 50%; + padding: 3rem; + margin: 0 auto; + border-radius: 5px; + background: white; +} +.status{ + font-weight: bold; + font-size: 18px; +} +.ver_text{ + margin:1rem; + font-size: 14px; + text-align: center; +} +.mainContainer{ + background:gainsboro; + height: 100vh; + padding-top: 10rem; +} +@media only screen and (max-width: 768px) { + .message_container{ + width:90%; + } +} \ No newline at end of file diff --git a/Apply-For-Me-UI/src/pages/pricing_plan/Pricing.jsx b/Apply-For-Me-UI/src/pages/pricing_plan/Pricing.jsx index ff5d13fd..cce1128a 100644 --- a/Apply-For-Me-UI/src/pages/pricing_plan/Pricing.jsx +++ b/Apply-For-Me-UI/src/pages/pricing_plan/Pricing.jsx @@ -1,22 +1,26 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import styles from "pages/pricing_plan/pricing.module.css"; -import { Link, useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router-dom"; //Importing bluebutton component import BlueBorderButton from "components/buttons/blue_border_button/BlueBorderButton"; //The question component import Question from "pages/pricing_plan/question/Question"; +import Plans3 from "./components/Plans3"; +import Plans4 from "./components/Plans4"; import Nav from "components/nav/Nav"; import Footer from "components/footer/Footer"; -import BlueButton from "components/buttons/blue_background/BlueButton"; -import { useSelector } from "react-redux"; +//import BlueButton from "components/buttons/blue_background/BlueButton"; +//import { useSelector } from "react-redux"; +import { ToastContainer } from "react-toastify"; const Pricing = ({ primaryHeading, primaryText, plans, + plansFull, toggleInfo, faqSection, secondaryHeading, @@ -27,13 +31,21 @@ const Pricing = ({ monthly: true, yearly: false }); + const [paymentInterval, setpaymentInterval] = useState(); + const [seeMore, setSeeMore] = useState(false); - const { user } = useSelector(state => state.user); + useEffect(() => { + toggle.yearly + ? setpaymentInterval("yearly") + : setpaymentInterval("monthly"); + }, [toggle.yearly, paymentInterval]); + const navigate = useNavigate(); return ( <> -