Pavle Golubovic 3 lat temu
rodzic
commit
79849e5a85
47 zmienionych plików z 1828 dodań i 918 usunięć
  1. 288
    28
      frontend/package-lock.json
  2. 8
    1
      frontend/package.json
  3. 8
    10
      frontend/public/index.html
  4. 18
    0
      frontend/src/App.css
  5. 38
    22
      frontend/src/App.js
  6. BIN
      frontend/src/assets/Cookie.png
  7. BIN
      frontend/src/assets/nick.jpg
  8. 0
    106
      frontend/src/components/CardCareers.jsx
  9. 9
    11
      frontend/src/components/CareerCardsTemplates/CardCareers2.jsx
  10. 1
    1
      frontend/src/components/CareerCardsTemplates/CareerCard.jsx
  11. 210
    0
      frontend/src/components/CareerCardsTemplates/ExpandedCard.jsx
  12. 0
    108
      frontend/src/components/ExpandedCard.jsx
  13. 22
    0
      frontend/src/components/Testimonials.jsx
  14. 1
    1
      frontend/src/components/root/CustomLink.jsx
  15. 56
    88
      frontend/src/components/shared/ClientForm.jsx
  16. 29
    6
      frontend/src/components/shared/Contact.jsx
  17. 46
    0
      frontend/src/components/shared/CookieBanner.jsx
  18. 15
    0
      frontend/src/components/shared/GradientWrapper.jsx
  19. 1
    1
      frontend/src/components/shared/HashPositions.jsx
  20. 86
    11
      frontend/src/components/shared/JobForm.jsx
  21. 4
    5
      frontend/src/components/shared/MyDropzone.jsx
  22. 1
    1
      frontend/src/components/shared/PageTitle.jsx
  23. 21
    0
      frontend/src/components/shared/PageTitleOneFont.jsx
  24. 33
    0
      frontend/src/components/shared/ReactHelmet.jsx
  25. 2
    1
      frontend/src/context/index.js
  26. 10
    13
      frontend/src/hooks/useAnalytics.js
  27. 17
    0
      frontend/src/hooks/useDataApi.js
  28. 8
    6
      frontend/src/index.js
  29. 35
    3
      frontend/src/pages/About.jsx
  30. 83
    34
      frontend/src/pages/Careers.jsx
  31. 141
    140
      frontend/src/pages/CaseStudy.jsx
  32. 13
    5
      frontend/src/pages/CaseStudyBI.jsx
  33. 24
    26
      frontend/src/pages/CaseStudyCentralized.jsx
  34. 12
    6
      frontend/src/pages/CaseStudyFinantial.jsx
  35. 4
    8
      frontend/src/pages/CaseStudyResource.jsx
  36. 5
    8
      frontend/src/pages/CaseStudyStrata.jsx
  37. 6
    11
      frontend/src/pages/CaseStudyTicketing.jsx
  38. 8
    4
      frontend/src/pages/ContactPage.jsx
  39. 22
    3
      frontend/src/pages/Home.jsx
  40. 34
    3
      frontend/src/pages/Portfolio.jsx
  41. 7
    10
      frontend/src/pages/ProcessPage.jsx
  42. 257
    199
      frontend/src/pages/WorkWithUs.jsx
  43. 2
    2
      frontend/src/styles/buttons.css
  44. 17
    1
      frontend/src/styles/text.css
  45. 13
    0
      frontend/src/utils/strapiApiBuilder.js
  46. 95
    25
      frontend/tailwind.config.js
  47. 118
    10
      frontend/yarn.lock

+ 288
- 28
frontend/package-lock.json Wyświetl plik

@@ -1,12 +1,12 @@
{
"name": "frontend",
"version": "1.0.20",
"version": "1.1.18",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "frontend",
"version": "1.0.20",
"version": "1.1.18",
"dependencies": {
"@faceless-ui/slider": "^1.1.14",
"@faceless-ui/window-info": "^2.1.1",
@@ -21,12 +21,19 @@
"emailjs": "^4.0.0",
"emailjs-com": "^3.2.0",
"eslint-plugin-prettier": "^4.0.0",
"form-data": "^4.0.0",
"formik": "^2.2.9",
"framer-motion": "^6.3.4",
"mailgun.js": "^8.0.6",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-cookie": "^4.1.1",
"react-dom": "^17.0.2",
"react-dropzone": "^12.0.5",
"react-ga": "^3.3.1",
"react-ga4": "^1.4.1",
"react-google-recaptcha": "^2.1.0",
"react-helmet-async": "^1.3.0",
"react-mailchimp-subscribe": "^2.1.3",
"react-markdown": "^8.0.0",
"react-router-dom": "^6.2.1",
@@ -3609,6 +3616,11 @@
"@types/node": "*"
}
},
"node_modules/@types/cookie": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
"integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
},
"node_modules/@types/debug": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
@@ -3682,6 +3694,15 @@
"@types/unist": "*"
}
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@@ -3781,8 +3802,7 @@
"node_modules/@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
"peer": true
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
},
"node_modules/@types/q": {
"version": "1.5.5",
@@ -3803,7 +3823,6 @@
"version": "18.0.21",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz",
"integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==",
"peer": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@@ -3826,8 +3845,7 @@
"node_modules/@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
"peer": true
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
},
"node_modules/@types/serve-index": {
"version": "1.9.1",
@@ -5104,6 +5122,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base-64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
},
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -6199,8 +6222,7 @@
"node_modules/csstype": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
"peer": true
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
@@ -7953,9 +7975,9 @@
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw=="
},
"node_modules/follow-redirects": {
"version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
@@ -8156,9 +8178,9 @@
}
},
"node_modules/form-data": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -11258,6 +11280,19 @@
}
}
},
"node_modules/jsdom/node_modules/form-data": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@@ -11556,6 +11591,25 @@
"sourcemap-codec": "^1.4.4"
}
},
"node_modules/mailgun.js": {
"version": "8.0.6",
"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-8.0.6.tgz",
"integrity": "sha512-b+c7QO1T4oFsudEcRB2H7oZKth8ZDeYRW4xjW12QQVNYDSJCVxqSQfps6ofcH8fqcCMJdzc76HVNGdnUZgBPCw==",
"dependencies": {
"axios": "^0.27.2",
"base-64": "^1.0.0",
"url-join": "^4.0.1"
}
},
"node_modules/mailgun.js/node_modules/axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"dependencies": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -14385,6 +14439,31 @@
"node": ">=14"
}
},
"node_modules/react-async-script": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
"integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
"dependencies": {
"hoist-non-react-statics": "^3.3.0",
"prop-types": "^15.5.0"
},
"peerDependencies": {
"react": ">=16.4.1"
}
},
"node_modules/react-cookie": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz",
"integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==",
"dependencies": {
"@types/hoist-non-react-statics": "^3.0.1",
"hoist-non-react-statics": "^3.0.0",
"universal-cookie": "^4.0.0"
},
"peerDependencies": {
"react": ">= 16.3.0"
}
},
"node_modules/react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@@ -14541,6 +14620,53 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
},
"node_modules/react-ga": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.1.tgz",
"integrity": "sha512-4Vc0W5EvXAXUN/wWyxvsAKDLLgtJ3oLmhYYssx+YzphJpejtOst6cbIHCIyF50Fdxuf5DDKqRYny24yJ2y7GFQ==",
"peerDependencies": {
"prop-types": "^15.6.0",
"react": "^15.6.2 || ^16.0 || ^17 || ^18"
}
},
"node_modules/react-ga4": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-1.4.1.tgz",
"integrity": "sha512-ioBMEIxd4ePw4YtaloTUgqhQGqz5ebDdC4slEpLgy2sLx1LuZBC9iYCwDymTXzcntw6K1dHX183ulP32nNdG7w=="
},
"node_modules/react-google-recaptcha": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-2.1.0.tgz",
"integrity": "sha512-K9jr7e0CWFigi8KxC3WPvNqZZ47df2RrMAta6KmRoE4RUi7Ys6NmNjytpXpg4HI/svmQJLKR+PncEPaNJ98DqQ==",
"dependencies": {
"prop-types": "^15.5.0",
"react-async-script": "^1.1.1"
},
"peerDependencies": {
"react": ">=16.4.1"
}
},
"node_modules/react-helmet-async": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
"integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"invariant": "^2.2.4",
"prop-types": "^15.7.2",
"react-fast-compare": "^3.2.0",
"shallowequal": "^1.1.0"
},
"peerDependencies": {
"react": "^16.6.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-helmet-async/node_modules/react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -16767,6 +16893,15 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/universal-cookie": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz",
"integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==",
"dependencies": {
"@types/cookie": "^0.3.3",
"cookie": "^0.4.0"
}
},
"node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
@@ -16805,6 +16940,11 @@
"punycode": "^2.1.0"
}
},
"node_modules/url-join": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -20362,6 +20502,11 @@
"@types/node": "*"
}
},
"@types/cookie": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
"integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
},
"@types/debug": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
@@ -20435,6 +20580,15 @@
"@types/unist": "*"
}
},
"@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@@ -20534,8 +20688,7 @@
"@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
"peer": true
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
},
"@types/q": {
"version": "1.5.5",
@@ -20556,7 +20709,6 @@
"version": "18.0.21",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz",
"integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==",
"peer": true,
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@@ -20579,8 +20731,7 @@
"@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
"peer": true
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
},
"@types/serve-index": {
"version": "1.9.1",
@@ -21538,6 +21689,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"base-64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
},
"batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -22354,8 +22510,7 @@
"csstype": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
"peer": true
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
"damerau-levenshtein": {
"version": "1.0.8",
@@ -23658,9 +23813,9 @@
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw=="
},
"follow-redirects": {
"version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA=="
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"fork-ts-checker-webpack-plugin": {
"version": "6.5.0",
@@ -23788,9 +23943,9 @@
}
},
"form-data": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -26005,6 +26160,18 @@
"whatwg-url": "^8.5.0",
"ws": "^7.4.6",
"xml-name-validator": "^3.0.0"
},
"dependencies": {
"form-data": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"jsesc": {
@@ -26250,6 +26417,27 @@
"sourcemap-codec": "^1.4.4"
}
},
"mailgun.js": {
"version": "8.0.6",
"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-8.0.6.tgz",
"integrity": "sha512-b+c7QO1T4oFsudEcRB2H7oZKth8ZDeYRW4xjW12QQVNYDSJCVxqSQfps6ofcH8fqcCMJdzc76HVNGdnUZgBPCw==",
"requires": {
"axios": "^0.27.2",
"base-64": "^1.0.0",
"url-join": "^4.0.1"
},
"dependencies": {
"axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"requires": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
}
}
},
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -28094,6 +28282,25 @@
"whatwg-fetch": "^3.6.2"
}
},
"react-async-script": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
"integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
"requires": {
"hoist-non-react-statics": "^3.3.0",
"prop-types": "^15.5.0"
}
},
"react-cookie": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz",
"integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==",
"requires": {
"@types/hoist-non-react-statics": "^3.0.1",
"hoist-non-react-statics": "^3.0.0",
"universal-cookie": "^4.0.0"
}
},
"react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@@ -28210,6 +28417,45 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
},
"react-ga": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.1.tgz",
"integrity": "sha512-4Vc0W5EvXAXUN/wWyxvsAKDLLgtJ3oLmhYYssx+YzphJpejtOst6cbIHCIyF50Fdxuf5DDKqRYny24yJ2y7GFQ==",
"requires": {}
},
"react-ga4": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-1.4.1.tgz",
"integrity": "sha512-ioBMEIxd4ePw4YtaloTUgqhQGqz5ebDdC4slEpLgy2sLx1LuZBC9iYCwDymTXzcntw6K1dHX183ulP32nNdG7w=="
},
"react-google-recaptcha": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-2.1.0.tgz",
"integrity": "sha512-K9jr7e0CWFigi8KxC3WPvNqZZ47df2RrMAta6KmRoE4RUi7Ys6NmNjytpXpg4HI/svmQJLKR+PncEPaNJ98DqQ==",
"requires": {
"prop-types": "^15.5.0",
"react-async-script": "^1.1.1"
}
},
"react-helmet-async": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
"integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==",
"requires": {
"@babel/runtime": "^7.12.5",
"invariant": "^2.2.4",
"prop-types": "^15.7.2",
"react-fast-compare": "^3.2.0",
"shallowequal": "^1.1.0"
},
"dependencies": {
"react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
}
}
},
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -29856,6 +30102,15 @@
"unist-util-is": "^5.0.0"
}
},
"universal-cookie": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz",
"integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==",
"requires": {
"@types/cookie": "^0.3.3",
"cookie": "^0.4.0"
}
},
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
@@ -29884,6 +30139,11 @@
"punycode": "^2.1.0"
}
},
"url-join": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

+ 8
- 1
frontend/package.json Wyświetl plik

@@ -1,6 +1,6 @@
{
"name": "frontend",
"version": "1.1.1",
"version": "1.1.18",
"private": true,
"dependencies": {
"@faceless-ui/slider": "^1.1.14",
@@ -16,12 +16,19 @@
"emailjs": "^4.0.0",
"emailjs-com": "^3.2.0",
"eslint-plugin-prettier": "^4.0.0",
"form-data": "^4.0.0",
"formik": "^2.2.9",
"framer-motion": "^6.3.4",
"mailgun.js": "^8.0.6",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-cookie": "^4.1.1",
"react-dom": "^17.0.2",
"react-dropzone": "^12.0.5",
"react-ga": "^3.3.1",
"react-ga4": "^1.4.1",
"react-google-recaptcha": "^2.1.0",
"react-helmet-async": "^1.3.0",
"react-mailchimp-subscribe": "^2.1.3",
"react-markdown": "^8.0.0",
"react-router-dom": "^6.2.1",

+ 8
- 10
frontend/public/index.html Wyświetl plik

@@ -5,10 +5,7 @@
<link rel="icon" href="%PUBLIC_URL%/favicon_diligent.png" />
<meta name="viewport" content="width=device-width, height=device-height" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Diligent Software's Website"
/>
<meta name="description" content="Diligent Software's Website" data-rh="true" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
@@ -27,15 +24,16 @@
<title>Diligent Software</title>

<!-- Google tag (gtag.js) -->
<!-- <script async src='https://www.googletagmanager.com/gtag/js?id=G-PTZC3WLTZ1'></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-PD7YZVDG30"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-PTZC3WLTZ1');
</script> -->
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());

gtag("config", "G-PD7YZVDG30");
</script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>

+ 18
- 0
frontend/src/App.css Wyświetl plik

@@ -22,6 +22,24 @@ body {
scrollbar-width: none; /* Firefox */
}

.radial-gradient {
background: radial-gradient(circle, #ffffff00, #8468BF 60%);
}
.scale-image {
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: center;
transform-origin: center;
}
@media only screen and (max-width: 650px) {
.scale-image {
-webkit-transform: scale(1.5);
transform: scale(1.5);
-webkit-transform-origin: center;
transform-origin: center;
}
}

@media only screen and (max-width: 500px) {
.size-07 {
transform: scale(0.7);

+ 38
- 22
frontend/src/App.js Wyświetl plik

@@ -2,13 +2,14 @@ import React, { useEffect, lazy, Suspense, useRef, useState } from 'react';
import './App.css';
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import Navigation from './components/shared/Navigation';
import CookieBanner from './components/shared/CookieBanner';
import Footer from './components/shared/Footer';
import Loader from './components/shared/Loader';
import ScrollToTop from './components/root/ScrollToTop';

import ReactGA from 'react-ga4';
import { useCookies, Cookies } from 'react-cookie';
import routes from './routes';


const Home = lazy(() => import('./pages/Home'));
const Portfolio = lazy(() => import('./pages/Portfolio'));
const Services = lazy(() => import('./pages/Services'));
@@ -29,24 +30,26 @@ const WorkWithUs = lazy(() => import('./pages/WorkWithUs'));
// Navigation Links
const links = routes.filter(item => item.nav === true);



function App() {
//tabs for contact form
const link = useNavigate();

const [cookies, setCookie, removeCookie] = useCookies(['user']);
const [diligentCookie, setDiligentCookie] = useState(cookies.diligent_ga);
//scroll to Contact segment
const forwardedRef = useRef(null);

//initialize analytics page tracking
//usePageTracking();
useEffect(() => {
if (diligentCookie === 'true') {
ReactGA.initialize(process.env.REACT_APP_MEASUREMENT_ID);
}
}, [diligentCookie]);

//scroll to Contact fn
function scrollToView(event) {
event.preventDefault();
if (forwardedRef) {
//console.log(forwardedRef.current.offsetTop);
window.scrollTo({ behavior: 'smooth', top: forwardedRef.current.offsetTop })
window.scrollTo({ behavior: 'smooth', top: forwardedRef.current.offsetTop });
} else {
link('/contact');
}
@@ -62,6 +65,16 @@ function App() {
}
}

const handleAccept = () => {
setCookie('diligent_ga', 'true', { path: '/' });
setDiligentCookie(prevValue => !prevValue);
};

const handleDecline = () => {
setCookie('diligent_ga', 'false', { path: '/' });
setDiligentCookie(prevValue => !prevValue);
};

return (
<div>
<ScrollToTop />
@@ -71,22 +84,25 @@ function App() {
activeLinks={activeLinks}
forwardedRef={forwardedRef}
></Navigation>
{diligentCookie === undefined && (
<CookieBanner handleAccept={handleAccept} handleDecline={handleDecline} />
)}
<Suspense fallback={<Loader />}>
<Routes>
<Route exact path="/" element={<Home forwardedRef={forwardedRef} />}/>
<Route exact path="/workwithus" element={<WorkWithUs />}/>
<Route exact path="/portfolio" element={<Portfolio />}/>
<Route exact path="/process" element={<ProcessPage />}/>
<Route exact path="/careers" element={<Careers />}/>
<Route exact path="/about" element={<About />}/>
<Route exact path="/contact" element={<ContactPage />}/>
<Route exact path="/casestudybi" element={<CaseStudyBI />}/>
<Route exact path="/casestudystrata" element={<CaseStudyStrata />}/>
<Route exact path="/casestudyfinancial" element={<CaseStudyFinantial />}/>
<Route exact path="/casestudycentralized" element={<CaseStudyCentralized />}/>
<Route exact path="/casestudyresource" element={<CaseStudyResource />}/>
<Route exact path="/casestudyticketing" element={<CaseStudyTicketing />}/>
<Route exact path="/privacypolicy" element={<PrivacyPolicy />}/>
<Route exact path="/" element={<Home forwardedRef={forwardedRef} />} />
<Route exact path="/workwithus" element={<WorkWithUs />} />
<Route exact path="/portfolio" element={<Portfolio />} />
<Route exact path="/process" element={<ProcessPage />} />
<Route exact path="/careers" element={<Careers />} />
<Route exact path="/about" element={<About />} />
<Route exact path="/contact" element={<ContactPage />} />
<Route exact path="/casestudybi" element={<CaseStudyBI />} />
<Route exact path="/casestudystrata" element={<CaseStudyStrata />} />
<Route exact path="/casestudyfinancial" element={<CaseStudyFinantial />} />
<Route exact path="/casestudycentralized" element={<CaseStudyCentralized />} />
<Route exact path="/casestudyresource" element={<CaseStudyResource />} />
<Route exact path="/casestudyticketing" element={<CaseStudyTicketing />} />
<Route exact path="/privacypolicy" element={<PrivacyPolicy />} />
</Routes>
</Suspense>


BIN
frontend/src/assets/Cookie.png Wyświetl plik


BIN
frontend/src/assets/nick.jpg Wyświetl plik


+ 0
- 106
frontend/src/components/CardCareers.jsx Wyświetl plik

@@ -1,106 +0,0 @@
import propTypes from 'prop-types';

import { useState } from 'react';
import { ReactComponent as BackTriangle } from '../assets/graphics/BackTriangle.svg';
import TriangleButton from './shared/TriangleButton';

const api_url = process.env.REACT_APP_API_URL;



export default function CardCareers(props) {
const [hideJob, setHideJob] = useState(true);

return (

<div
className={'transition-all hover:transition-all pb-0 hover:pb-12 flex flex-col justify-center items-center w-4/5 lg:w-5/6 mb-8 lg:mb-0 lg:mr-8 group'
}
>
{/* Collapsed Card */}
{ hideJob && <div>
<img
src={api_url + props.image}
className={
'ml-auto mr-auto block w-2/5 bg-baby-blue text-dark-gray rounded-full p-4'
}
/>
<h3 className={'mt-6 font-semibold text-2xl'}>
{props.heading}
</h3>
<p className={'mt-6 text-sm'}>{props.paragraph}</p>
<a
href={'#' + props.heading.split(' ')[0]}
onClick={() => setHideJob(!hideJob)}
className={'min-w-max btn btn_primary mt-8 opacity-0 transition-all group-hover:opacity-100 group-hover:transition-all'
}
>
Read More
</a>
</div>}

{/* Expanded Job */}
{ !hideJob && <div
id={props.heading.split(' ')[0]}
className={
!hideJob
? 'hidden'
: 'dark:text-white w-full h-fit shadow-md rounded-md px-12 lg:px-16 py-12 lg:py-16'
}
>
<div className="flex flex-col items-start justify-center text-left">
<div className="flex flex-row items-center justify-start">
<div className='mr-4'>
<TriangleButton onClick={() => setHideJob(!hideJob)} direction={'left'}/>
</div>

<img
src={api_url + props.image}
className="ml-auto mr-auto block w-2/5 bg-baby-blue text-dark-gray rounded-full p-4"
/>
<h3 className="ml-6 w-full font-semibold text-2xl">{props.heading}</h3>
</div>
<p className="mt-6 text-sm">{props.paragraph}</p>
<h4 className="mt-6 font-semibold text-lg">{props.requirements_heading}</h4>
<p className="mt-6 text-sm">{props.requirements_paragraph}</p>
<br />
<h4 className="mt-6 font-semibold text-lg">{props.expectations_heading}</h4>
<p className="mt-6 text-sm">{props.expectations_paragraph}</p>
<h4 className="mt-6 font-semibold text-lg">{props.benefits_heading}</h4>
<p className="mt-6 text-sm">{props.benefits_paragraph}</p>
<div className="flex flex-row w-full items-center justify-end">
<a
href="#contact"
onClick={() => {
setHideJob(!hideJob);
props.setClickedPosition('#' + props.hash_position);
}}
className="btn btn_primary mt-8 transition-all hover:transition-all"
>
Apply
</a>
</div>
</div>
</div>}

</div>
);
}

CardCareers.propTypes = {
key: propTypes.number,
image: propTypes.string,
heading: propTypes.string,
paragraph: propTypes.string,
requirements_heading: propTypes.string,
requirements_paragraph: propTypes.string,
expectations_heading: propTypes.string,
expectations_paragraph: propTypes.string,
benefits_heading: propTypes.string,
benefits_paragraph: propTypes.string,
hash_position: propTypes.string,
setClickedPosition: propTypes.func,
};

frontend/src/components/CardCareers2.jsx → frontend/src/components/CareerCardsTemplates/CardCareers2.jsx Wyświetl plik

@@ -1,15 +1,11 @@
import propTypes from 'prop-types';

import { useEffect, useState } from 'react';
import { ReactComponent as BackTriangle } from '../assets/graphics/BackTriangle.svg';
import Wrapper from '../layout/Wrapper';
import { useState } from 'react';
import Wrapper from '../../layout/Wrapper';
import ExpandedCard from './ExpandedCard';
import TriangleButton from './shared/TriangleButton';
import CareerCard from './CareerCard';
import Grid from '../layout/Grid';
import { ref } from 'yup';
import useClickOutside from '../hooks/useClickOutside';
import useComponentVisible from '../hooks/useClickOutside';
//import useClickOutside from '../../hooks/useClickOutside';
import useComponentVisible from '../../hooks/useClickOutside';

const api_url = process.env.REACT_APP_API_URL;

@@ -29,12 +25,14 @@ export default function CardCareers2({ cards }) {
{isComponentVisible ?
<ExpandedCard card={expandedCard} setExpanded={setIsComponentVisible} setExpandedCard={setExpandedCard}></ExpandedCard>
:
<div className='flex flex-row justify-center w-full'>
{
<div className='flex flex-col md:flex-row justify-center w-full gap-8'>
{/* {
cards.map((item, index) => (
<CareerCard card={item} key={index} setExpanded={setIsComponentVisible} setExpandedCard={setExpandedCard} />
))
}
} */}
<CareerCard card={cards.NetDev} setExpanded={setIsComponentVisible} setExpandedCard={setExpandedCard} />
{/* <CareerCard card={cards.NetDevIntern} setExpanded={setIsComponentVisible} setExpandedCard={setExpandedCard} /> */}

</div>
}

frontend/src/components/CareerCard.jsx → frontend/src/components/CareerCardsTemplates/CareerCard.jsx Wyświetl plik

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import net from './../assets/icons/net.svg';
import net from './../../assets/icons/net.svg';

const _card = {
role: '.Net Developer',

+ 210
- 0
frontend/src/components/CareerCardsTemplates/ExpandedCard.jsx Wyświetl plik

@@ -0,0 +1,210 @@
import React, { useContext, useEffect } from 'react';
import PropTypes from 'prop-types';
import TriangleButton from '../shared/TriangleButton';
import { useNavigate } from 'react-router-dom';
import net from './../../assets/icons/net.svg';
import { m } from 'framer-motion';
import useClickOutside from '../../hooks/useClickOutside';
import { UIContext } from '../../context';

const _data = {
requirements: [
'Good software development fundamentals and knowledge of .NET architecture concepts & patterns',
'Good knowledge of software design patterns',
'Good knowledge of databases and database design',
'Experience in working with microservices is a big plus',
'The ability to work in a big team but also to work independently',
'Excellent communication skills',
],
key: [
'Working as a full-stack developer on various project and products',
'Working with 3rd-party APIs',
'Working on different integration scenarios',
'Setting up project structure and architecture',
'Being involved in full project development, from writing a specification to deploying a finished product',
],
offer: [
'Full Remote position',
'A fast-growth company with stable projects and strong international clients',
'Opportunity to work in teams with experienced engineers',
'Competitive employment conditions',
'An environment that will make you feel good about your job',
'Challenging and diverse projects',
'Support in your personal and professional growth',
'Flexible working hours',
'Private health insurance',
],
};

const _card = {
role: '.Net Developer',
shortDetails:
'Team Diligent is constantly growing! We are looking for a team player that will work with experienced engineers. If technology is your passion and you are ready to move the boundaries of your knowledge every day, then, Diligent is the right place for you. If you are not from Niš, we are offering a full remote position.',
};

const ExpandedCard = ({ card, setExpanded, setExpandedCard }) => {
const linkTo = useNavigate();

const {uiContext, setUiContext} = useContext(UIContext);

useEffect(() => {
console.log(card);
}, [])

function handleContext(id) {
setUiContext({
...uiContext,
tab: id,
});
}

return (
<div
className={
'dark:text-white card-no-hover w-full h-fit shadow-md rounded-md px-12 lg:px-32 py-12 lg:py-16'
}
>
{card.templateFlag === 1 && (
<div className="flex flex-col items-start justify-center text-left">
<div className="flex flex-row items-center justify-start">
<div className="mr-4 lg:hidden">
<TriangleButton
onClick={() => {
setExpanded(false);
setExpandedCard({});
}}
direction={'left'}
/>
</div>
<div className="hidden lg:block absolute top-20 left-12">
<TriangleButton
onClick={() => {
setExpanded(false);
setExpandedCard({});
}}
direction={'left'}
/>
</div>

<img
src={net}
className="ml-auto mr-auto block w-[70px] bg-baby-blue text-dark-gray"
/>
<h3 className="ml-6 w-full font-semibold text-2xl">{card.role}</h3>
</div>
<p className="mt-6 text-sm">{card.extended.shortDetails}</p>
<h4 className="mt-6 font-semibold text-lg">Key Responsibilities:</h4>
<ul>
{_data.key.map((item, index) => (
<li className="list-disc ml-6" key={index}>
{item}
</li>
))}
</ul>
<br />
<h4 className="mt-6 font-semibold text-lg">Requirements:</h4>
<ul>
{_data.requirements.map((item, index) => (
<li className="list-disc ml-6" key={index}>
{item}
</li>
))}
</ul>
<br />
<h4 className="mt-6 font-semibold text-lg">What We Offer:</h4>
<ul>
{_data.offer.map((item, index) => (
<li className="list-disc ml-6" key={index}>
{item}
</li>
))}
</ul>
<br />
<div className="flex flex-row w-full items-center justify-end">
<a
href="/contact"
className="btn btn_primary mt-8 transition-all hover:transition-all"
onClick={()=> handleContext(card.id)}
>
Apply
</a>
</div>
</div>
)}
{card.templateFlag === 2 && (
<div className="flex flex-col items-start justify-center text-left">
<div className="flex flex-row items-center justify-start">
<div className="mr-4 lg:hidden">
<TriangleButton
onClick={() => {
setExpanded(false);
setExpandedCard({});
}}
direction={'left'}
/>
</div>
<div className="hidden lg:block absolute top-20 left-12">
<TriangleButton
onClick={() => {
setExpanded(false);
setExpandedCard({});
}}
direction={'left'}
/>
</div>

<img
src={net}
className="ml-auto mr-auto block w-[70px] bg-baby-blue text-dark-gray"
/>
<h3 className="ml-6 w-full font-semibold text-2xl">{card.role}</h3>
</div>
<p className="mt-6 text-sm">{card.extended.paragraph}</p>
<h4 className="mt-6 font-semibold text-lg">What We Offer:</h4>
<ul>
{card.extended.offer.map((item, index) => (
<li className="list-disc ml-6" key={index}>
{item}
</li>
))}
</ul>
<br />
<h4 className="mt-6 font-semibold text-lg">Requirements:</h4>
<ul>
{card.extended.requirements.map((item, index) => (
<li className="list-disc ml-6" key={index}>
{item}
</li>
))}
</ul>
<br />
<h4 className="mt-6 font-semibold text-lg">Our selection process has the following steps:</h4>
<ul>
{card.extended.selectionProcess.map((item, index) => (
<li className="list-decimal ml-6" key={index}>
{item}
</li>
))}
</ul>
<br />
<p className="mt-6 text-sm">{card.extended.conslusionParagraph}</p>
<br/>
<div className="flex flex-row w-full items-center justify-end">
<a
href="/contact"
className="btn btn_primary mt-8 transition-all hover:transition-all"
onClick={()=> handleContext(card.id)}
>
Apply
</a>
</div>
</div>
)}
</div>
);
};

ExpandedCard.propTypes = {};

export default ExpandedCard;

+ 0
- 108
frontend/src/components/ExpandedCard.jsx Wyświetl plik

@@ -1,108 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import TriangleButton from './shared/TriangleButton';
import { useNavigate } from 'react-router-dom';
import net from './../assets/icons/net.svg';
import { m } from 'framer-motion';
import useClickOutside from '../hooks/useClickOutside';

const _data = {
requirements: [
'Good software development fundamentals and knowledge of .NET architecture concepts & patterns',
'Good knowledge of software design patterns',
'Good knowledge of databases and database design',
'Experience in working with microservices is a big plus',
'The ability to work in a big team but also to work independently',
'Excellent communication skills'
],
key: [
'Working as a full-stack developer on various project and products',
'Working with 3rd-party APIs',
'Working on different integration scenarios',
'Setting up project structure and architecture',
'Being involved in full project development, from writing a specification to deploying a finished product'
],
offer: [
'Full Remote position',
'A fast-growth company with stable projects and strong international clients',
'Opportunity to work in teams with experienced engineers',
'Competitive employment conditions',
'An environment that will make you feel good about your job',
'Challenging and diverse projects',
'Support in your personal and professional growth',
'Flexible working hours',
'Private health insurance'
],

}

const _card = {
role: '.Net Developer',
shortDetails: 'Team Diligent is constantly growing! We are looking for a team player that will work with experienced engineers. If technology is your passion and you are ready to move the boundaries of your knowledge every day, then, Diligent is the right place for you. If you are not from Niš, we are offering a full remote position.',

}

const ExpandedCard = ({card, setExpanded, setExpandedCard}) => {

const linkTo = useNavigate();

return (
<div
className={
'dark:text-white card-no-hover w-full h-fit shadow-md rounded-md px-12 lg:px-32 py-12 lg:py-16'
}
>
<div className="flex flex-col items-start justify-center text-left">
<div className="flex flex-row items-center justify-start">
<div className='mr-4 lg:hidden'>
<TriangleButton onClick={() => {setExpanded(false); setExpandedCard({})}} direction={'left'}/>
</div>
<div className='hidden lg:block absolute top-20 left-12'>
<TriangleButton onClick={() => {setExpanded(false); setExpandedCard({})}} direction={'left'}/>
</div>

<img
src={net}
className="ml-auto mr-auto block w-[70px] bg-baby-blue text-dark-gray"
/>
<h3 className="ml-6 w-full font-semibold text-2xl">{card.role}</h3>
</div>
<p className="mt-6 text-sm">{_card.shortDetails}</p>
<h4 className="mt-6 font-semibold text-lg">Key Responsibilities:</h4>
<ul>
{_data.key.map((item, index) => (
<li className='list-disc ml-6' key={index}>{item}</li>
))}
</ul>
<br />
<h4 className="mt-6 font-semibold text-lg">Requirements:</h4>
<ul>
{_data.requirements.map((item, index) => (
<li className='list-disc ml-6' key={index}>{item}</li>
))}
</ul>
<br />
<h4 className="mt-6 font-semibold text-lg">What We Offer:</h4>
<ul>
{_data.offer.map((item, index) => (
<li className='list-disc ml-6' key={index}>{item}</li>
))}
</ul>
<br />
<div className="flex flex-row w-full items-center justify-end">
<a
href="/contact"
className="btn btn_primary mt-8 transition-all hover:transition-all"
>
Apply
</a>
</div>
</div>
</div>
)
}

ExpandedCard.propTypes = {}

export default ExpandedCard

+ 22
- 0
frontend/src/components/Testimonials.jsx Wyświetl plik

@@ -8,6 +8,7 @@ import PageTitle from './shared/PageTitle';
import TestimonialCard from './shared/TestimonialCard';
import Boza from './../assets/boza.jpg';
import Peter from './../assets/peter1.png';
import Nick from './../assets/nick.jpg';
import ns from './../assets/ns.png';

const _data = {
@@ -37,6 +38,13 @@ const _data = {
clientImg: ns,
alt: 'Niš Ekspres',
},
{
clientName: 'Nick Pericle',
paragraph: `We've partnered with the team at Diligent Software for 3 years. We've built over a dozen apps together, and each time we're impressed by Diligent's dedicated approach, and end result. We consider Diligent Software a trusted partner - the trust we share, the flexibility, and the quality we get are just what we need. I can't recommend Diligent enough as a partner.`,
clientRole: 'VP of Operations @ Profit Optics',
clientImg: Nick,
alt: 'Nick',
},
],
};

@@ -79,6 +87,13 @@ export default function Testimonials({ noTitle }) {
imageAlt={_data.cards[2].alt}
paragraph={_data.cards[2].paragraph}
/>
<TestimonialCard
clientName={_data.cards[3].clientName}
clientRole={_data.cards[3].clientRole}
clientImg={_data.cards[3].clientImg}
imageAlt={_data.cards[3].alt}
paragraph={_data.cards[3].paragraph}
/>
</div>
{/*
<TestimonialCard/>
@@ -108,6 +123,13 @@ export default function Testimonials({ noTitle }) {
imageAlt={_data.cards[2].alt}
paragraph={_data.cards[2].paragraph}
/>
<TestimonialCard
clientName={_data.cards[3].clientName}
clientRole={_data.cards[3].clientRole}
clientImg={_data.cards[3].clientImg}
imageAlt={_data.cards[3].alt}
paragraph={_data.cards[3].paragraph}
/>
</FMCarousel>
)}
</div>

+ 1
- 1
frontend/src/components/root/CustomLink.jsx Wyświetl plik

@@ -9,7 +9,7 @@ const CustomLink = ({href, downloadFile, bg, txt, children}) => {
// {context}
// </a>
<Link {...{
className: 'flex gap-2 items-center px-[16px] py-[12px] text-p font-medium bg-[#8568BF] text-white rounded-full' ,
className: 'btn-primary w-fit items-center n-paragraph-title text-white rounded-[16px]' ,
to: href,
target: '_blank',
...(downloadFile && {download: downloadFile}),

+ 56
- 88
frontend/src/components/shared/ClientForm.jsx Wyświetl plik

@@ -1,3 +1,4 @@
import React, { useRef } from 'react';
import TagInput from '../TagInput';
import img from '../../assets/images/Inqueries.png';
import * as Yup from 'yup';
@@ -6,16 +7,16 @@ import { ClientFormContext } from '../../context';
import { useContext, useState } from 'react';
import * as emailjs from 'emailjs-com';
import { motion } from 'framer-motion';
import ReactGA from 'react-ga4';
import ReCAPTCHA from 'react-google-recaptcha';
import axios from 'axios';

const api_url = 'http://localhost:1337';

export default function ClientForm() {
export default function ClientForm({ mg }) {
//search context for prevous entry TODO
const { clientForm, setClientForm } = useContext(ClientFormContext);
const [sucMsg, setSucMsg] = useState(false);
const [errorMsg, setErrorMsg] = useState('');
const captchaRef = useRef(null);
const [msgText, setMsgText] = useState('');
const changeFormHandler = event => {
const { name, value } = event.target;
setClientForm({
@@ -60,82 +61,46 @@ export default function ClientForm() {
<Formik
initialValues={clientForm}
validationSchema={validationSchema}
onSubmit={values => {
let data = {};

const fetchData = async () => {
axios.get(`${api_url}/api/client-submissions?filters[Email][$eq]=${values.email}`)
.then((res) => {
data = res.data.data[0];
if (typeof data == 'undefined') {
}
const submitDate = new Date(data.attributes.SubmitDate);
const now = new Date();
if ((now.getMonth() - submitDate.getMonth()) < 1)
{
setErrorMsg('You Already sent an email');
//console.log('email already sent');
return false;
}
else {
fetch(`${api_url}/api/client-submissions/${data.id}`, {
method: "PUT",
headers: {
"Content-type": "application/json; charset=UTF-8",
},
body: JSON.stringify({
data: {
SubmitDate: now,
}
})
}).then(r => r.json()).then(d => {
setErrorMsg('');
const val = {
Tag: values.tag,
Subject: values.subject,
Email: values.email,
Firstname: values.firstName,
Lastname: values.lastName,
Description: values.description,
}
// emailjs
// .send(
// process.env.REACT_APP_SERVICE_ID,
// process.env.REACT_APP_CLIENT_TEMPLATE_ID,
// val,
// process.env.REACT_APP_USER_ID,
// )
// .then(
// result => {
// console.log(result.text);
// setSucMsg(true);
// },
// error => {
// console.log(error.text);
// },
// );
}).catch(err => {
console.log(err)
return false
});
}
})
}
fetchData();
}}

onSubmit={async values => {
const data = {
Tag: values.tag,
Subject: values.subject,
Email: values.email,
Firstname: values.firstName,
Lastname: values.lastName,
Description: values.description,
};
const token = captchaRef.current.getValue();
captchaRef.current.reset();

if (token.length === 0) {
setSucMsg(true);
setMsgText('Please fill reCAPTCHA and try again. Thank you!');
} else {
await axios
.post(`${process.env.REACT_APP_CAPTCHA_API}/verify-token`, { token })
.then(res => {
setSucMsg(true);
if (res.data.data.success) {
setMsgText('Submission Succesful! Thank you!');
mg.messages.create('dilig.net', {
from: `${values.firstName} ${values.lastName} <${values.email}>`,
to: ['hr@dilig.net'],
subject: `${values.subject}`,
text: `${values.description}`,
html: `<p>${values.description}</p>`,
});
} else setMsgText('Please fill reCAPTCHA and try again. Thank you!');
})
.catch(error => {
console.log(error);
});
}
ReactGA.event('contact', {
category: 'Contact',
action: 'Business Inquiry',
});
}}
>
{props => (
<Form onSubmit={props.handleSubmit}>
@@ -261,7 +226,12 @@ export default function ClientForm() {
/>
</div>
</div>

<div className="items-center justify-end flex">
<ReCAPTCHA
sitekey={process.env.REACT_APP_SITE_KEY}
ref={captchaRef}
/>
</div>
<div className=" py-3 text-right">
<button
type="submit"
@@ -270,13 +240,11 @@ export default function ClientForm() {
Submit
</button>
</div>
{sucMsg && <div className={'text-sm text-right text-dg-primary-900'}>
Submission Succesful! Thank you!
</div> }
{errorMsg !== '' && <div className={'text-sm text-right text-red-700'}>
{errorMsg}
</div> }
{sucMsg && (
<div className={'text-sm text-right text-dg-primary-900'}>
{msgText}
</div>
)}
</div>

<div className="col-span-1 sm:col-span-1 lg:col-span-1"></div>

+ 29
- 6
frontend/src/components/shared/Contact.jsx Wyświetl plik

@@ -14,6 +14,17 @@ import { ClientFormContext } from '../../context';
import { JobFormContext } from '../../context';
import PageTitle from './PageTitle';
import Wrapper from '../../layout/Wrapper';
import { UIContext } from './../../context/index';

import Mailgun from 'mailgun.js';
import FormData from 'form-data';

const mailgun = new Mailgun(FormData);
const mg = mailgun.client({
username: 'api',
key: process.env.REACT_APP_MAILGUN_API_KEY,
url: 'https://api.eu.mailgun.net',
});

export default function Contact(props) {
const [tab, setTab] = useState(true);
@@ -27,7 +38,7 @@ export default function Contact(props) {
//if (event.button !== 0)
event.preventDefault();
}
const { uiContext, setUiContext } = useContext(UIContext);
const clientContext = useContext(ClientFormContext);
const jobContext = useContext(JobFormContext);

@@ -107,14 +118,25 @@ export default function Contact(props) {
<OrbitOnClick tab={tab} />
</div>
<div className="py-16 relative">
<div className="flex justify-end flex-col" >
<div className="flex justify-end flex-col">
<Tab.Group
defaultIndex={props.defaultIndex}
onChange={index => handleTab(index)}
>
<div className="flex flex-col md:flex-row items-start md:items-baseline md:justify-between" onMouseDown={handleTabClick}>
{tab ? <PageTitle left heading={"Tell Us About Your Idea!"} subheading={'Contact us'} /> : <PageTitle left heading={"Join Diligent!"} subheading={'Cotact us'} />}
<div
className="flex flex-col md:flex-row items-start md:items-baseline md:justify-between"
onMouseDown={handleTabClick}
>
{tab ? (
<PageTitle
left
heading={'Tell Us About Your Idea!'}
subheading={'Contact us'}
/>
) : (
<PageTitle left heading={'Join Diligent!'} subheading={'Cotact us'} />
)}

<Tab.List className="flex flex-row items-center md:flex-col lg:flex-row h-fit w-fit max-w-max md:ml-auto z-20 p-1 min-h-12 space-x-1 bg-dg-primary-400 rounded-xl my-4 align-middle">
<Tab
className={({ selected }) =>
@@ -148,7 +170,7 @@ export default function Contact(props) {
<Tab.Panels className="w-full mt-2 mx-auto">
<Tab.Panel className={classNames('py-3', 'outline-none')}>
<ClientFormContext.Provider value={{ clientForm, setClientForm }}>
<ClientForm />
<ClientForm mg={mg} />
</ClientFormContext.Provider>
</Tab.Panel>
<Tab.Panel className={classNames('py-3', 'outline-none')}>
@@ -156,6 +178,7 @@ export default function Contact(props) {
<JobForm
cntCareers={cntCareers}
defaultPositionSelection={defaultPositionSelection}
mg={mg}
/>
</JobFormContext.Provider>
</Tab.Panel>

+ 46
- 0
frontend/src/components/shared/CookieBanner.jsx Wyświetl plik

@@ -0,0 +1,46 @@
import '../../App.css';
import Wrapper from '../../layout/Wrapper';
import Cookie from './../../assets/Cookie.png';

const cookie_p =
'We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you’ve provided to them or that they’ve collected from your use of their services.';

const CookieBanner = ({ handleAccept, handleDecline }) => {
return (
<Wrapper>
<div className="flex flex-row items-start gap-8 xl:mr-0 mr-4 md:p-8 px-2 py-4 isolate max-w-banner fixed bg-dg-primary-75 shadow-custom z-50 bottom-0 rounded-2xl mb-3">
<img
src={Cookie}
alt="Diligent Cookie"
className="hidden md:block w-44 h-48 flex-none z-0 grow-0 order-none"
/>
<div className="flex flex-col items-start p-0 gap-2.5 max-w-banner">
<div className="flex flex-col items-start p-0 gap-4 max-w-banner ">
<p className="md:text-title text-banner-mobile text-dark-gray font-secondary font-semibold">
Our Website uses Cookies
</p>
<p className="flex items-center text-dark-gray font-secondary md:text-banner-p text-banner-p-mobile">
{cookie_p}
</p>
</div>
<div className="max-w-banner w-full flex items-center justify-end p-0 md:gap-2.5">
<button
onClick={handleDecline}
className="flex items-start p-0 text-dg-primary-900 bg-dg-primary-75 font-semibold font-secondary md:px-64p px-42p md:py-20p py-15p md:w-max w-36 whitespace-nowrap"
>
DECLINE
</button>
<button
onClick={handleAccept}
className="btn-primary flex flex-row items-start md:px-64p px-42p md:py-20p py-15p md:w-max w-36 whitespace-nowrap"
>
Accept
</button>
</div>
</div>
</div>
</Wrapper>
);
};

export default CookieBanner;

+ 15
- 0
frontend/src/components/shared/GradientWrapper.jsx Wyświetl plik

@@ -0,0 +1,15 @@
import React from 'react';

const GradientWrapper = ({ children, padding }) => {
return (
<div
className={
'px-[16px] md:px-0 bg-gradient-to-r from-[#90278F] to-[#8468BF]'
}
>
<div className={'max-w-custom md:text-center mx-auto flex flex-col gap-[16px]' + (padding ? ` ${padding}` : null) }>{children}</div>
</div>
);
};

export default GradientWrapper;

+ 1
- 1
frontend/src/components/shared/HashPositions.jsx Wyświetl plik

@@ -4,7 +4,7 @@ import propTypes from 'prop-types';

const _data = {
job: [{
id:0,
id:1,
position: ".Net"
},
]

+ 86
- 11
frontend/src/components/shared/JobForm.jsx Wyświetl plik

@@ -7,16 +7,23 @@ import { JobFormContext } from '../../context';
import { useContext, useState, useRef, useEffect } from 'react';
import * as emailjs from 'emailjs-com';
import { motion } from 'framer-motion';
import ReactGA from 'react-ga4';
import MyDropzone from './MyDropzone';
import HashPositions from './HashPositions';
<<<<<<< HEAD
import useDataApi from '../../hooks/useDataApi';
import axios from 'axios';

const api_url = 'http://localhost:1337';
=======
import ReCAPTCHA from 'react-google-recaptcha';
import axios from 'axios';
>>>>>>> staging

export default function JobForm(props) {
const [sucMsg, setSucMsg] = useState(false);
const captchaRef = useRef(null);
const [msgText, setMsgText] = useState('');
const cntCareersJobs = props.cntCareers;
let defaultPositionSelection = props.defaultPositionSelection;
//search context for prevous entry TODO
@@ -25,7 +32,7 @@ export default function JobForm(props) {
const [otherInputState, setOtherInputState] = useState(true);
const [selectedPosition, setSelectedPosition] = useState('');
const [errorMsg, setErrorMsg] = useState('');
const [errorMsgPosition, setErrorMsgPosition] = useState('');
const fileInput = useRef();

function changeFormHandler(event) {
@@ -73,6 +80,7 @@ export default function JobForm(props) {
.trim()
.min(2, 'Cover Letter too short')
.required('Cover Letter is Required'),
other: Yup.string(),
});

return (
@@ -89,11 +97,15 @@ export default function JobForm(props) {
initialValues={jobForm}
validationSchema={validationSchema}
onChange={changeFormHandler}
<<<<<<< HEAD
onSubmit={values => {

setSucMsg(false);

//prep file
=======
onSubmit={async values => {
>>>>>>> staging
const prepFile = async file => {
if (file.size >= 2000000) {
setErrorMsg('File too large!');
@@ -107,8 +119,8 @@ export default function JobForm(props) {
const convertBase64 = file => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);

fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
@@ -118,6 +130,7 @@ export default function JobForm(props) {
};
});
};
<<<<<<< HEAD

let data = {};

@@ -199,7 +212,64 @@ export default function JobForm(props) {
}
=======
if (
selectedPosition === '' ||
(otherInputState === false && values.other === '')
)
setErrorMsgPosition('Position is Required');
else {
setErrorMsgPosition('');
if (jobForm.file === '') {
setErrorMsg('CV is Required');
} else {
setErrorMsg('');
if (jobForm.file.size >= 2000000) {
setErrorMsg('File too large!');
} else {
const file = {
filename: 'CV.pdf',
data: jobForm.file,
};

const token = captchaRef.current.getValue();
captchaRef.current.reset();
if (token.length === 0) {
setSucMsg(true);
setMsgText('Please fill reCAPTCHA and try again. Thank you!');
} else {
await axios
.post(`${process.env.REACT_APP_CAPTCHA_API}/verify-token`, {
token,
})
.then(res => {
setSucMsg(true);
if (res.data.data.success) {
setMsgText('Submission Succesful! Thank you!');

props.mg.messages.create('dilig.net', {
from: `${values.firstName} ${values.lastName} <${values.email}>`,
to: ['hr@dilig.net'],
subject: 'Applying for a position',
text: `Email: ${values.email}, Position:${values.position} ${values.other}, Cover letter: ${values.coverLetter}, Link: ${values.link} `,
html: `<p>Email: ${values.email}</p><p>Position: ${selectedPosition} ${values.other}</p><p>Cover letter: ${values.coverLetter}</p><p>Link (optional): ${values.link}</p>`,
attachment: file,
});
} else
setMsgText('Please fill reCAPTCHA and try again. Thank you!');
})
.catch(error => {
console.log(error);
});
}
}
}
>>>>>>> staging
}
ReactGA.event('contact', {
category: 'Contact',
action: 'Job application',
});
}}
>
{props => (
@@ -258,14 +328,14 @@ export default function JobForm(props) {
onChange={props.handleChange}
className="mt-1 disabled:bg-gray-100 disabled:border-gray-300 dark:disabled:bg-gray-400 dark:disabled:border-gray-600 focus:ring-dg-primary-600 focus:border-dg-primary-900 dark:bg-dg-primary-1500 dark:text-white block w-full shadow-sm sm:text-sm border-dg-primary-600 rounded-md transition duration-200"
/>
</div>
{errorMsgPosition != '' ? (
<div className="h-4">
<ErrorMessage
name="other"
component="div"
className="text-sm text-right text-red-600"
/>
<div className="text-sm text-right text-red-600">
{errorMsgPosition}
</div>
</div>
</div>
) : null}
<div className="py-1">
<label
htmlFor="first-name"
@@ -420,7 +490,12 @@ export default function JobForm(props) {
<div className="text-sm text-right">{errorMsg}</div>
</div>
</div>

<div className="items-center justify-end flex">
<ReCAPTCHA
sitekey={process.env.REACT_APP_SITE_KEY}
ref={captchaRef}
/>
</div>
<div className=" py-3 text-right">
<button
type="submit"
@@ -431,7 +506,7 @@ export default function JobForm(props) {
</div>
{sucMsg && (
<div className={'text-sm text-right text-dg-primary-900'}>
Submission Succesful! Thank you!
{msgText}
</div>
)}
</div>

+ 4
- 5
frontend/src/components/shared/MyDropzone.jsx Wyświetl plik

@@ -8,7 +8,6 @@ export default function MyDropzone(props) {
const [file, setFile] = useState('');
const [empty, setEmpty] = useState(true);


function emptyFiles() {
const newFile = [];
setFile(newFile);
@@ -28,13 +27,13 @@ export default function MyDropzone(props) {
</svg>
);

const onDrop = useCallback(acceptedFiles => {
const onDrop = useCallback(async acceptedFiles => {
if (acceptedFiles && acceptedFiles.length > 0) {
if (acceptedFiles[0] !== 'undefined' && acceptedFiles[0].type !== 'undefined') {
if (acceptedFiles[0].type === 'application/pdf') {
acceptedFiles.map(file => {
setFile(file);
});
const files = Array.from(acceptedFiles);
const fileBuffer = await files[0];
setFile(fileBuffer);
setEmpty(false);
}
}

+ 1
- 1
frontend/src/components/shared/PageTitle.jsx Wyświetl plik

@@ -1,7 +1,7 @@
import React from "react";
import PropTypes from 'prop-types'

const PageTitle = ({heading, subheading, left, color,pb}) => {
const PageTitle = ({heading, subheading, left, color, pb }) => {
return (
<div className={"flex flex-col gap-8p"+ (left ? " text-left items-start":" text-center items-center") + (color ? " text-[#9B32CE]" : " ") + (pb ? ' pb-2' :' ')}>
<h6 className={"subheading" + (left ? " text-left":" text-center")}>{subheading}</h6>

+ 21
- 0
frontend/src/components/shared/PageTitleOneFont.jsx Wyświetl plik

@@ -0,0 +1,21 @@
import React from "react";
import PropTypes from 'prop-types'

const PageTitleOneFont = ({heading, subheading, left, color, pb }) => {
return (
<div className={"flex flex-col gap-8p"+ (left ? " text-left items-start":" text-center items-center") + (color ? " text-[#9B32CE]" : " ") + (pb ? ' pb-2' :' ')}>
<h6 className={"n-subheading" + (left ? " text-left":" text-center")}>{subheading}</h6>
<h1 className={"n-heading" + (left ? " text-left":" text-center")}>{heading}</h1>
</div>
)
}

PageTitleOneFont.propTypes = {
heading: PropTypes.string,
subheading: PropTypes.string,
left: PropTypes.bool,
color: PropTypes.bool,
}

export default PageTitleOneFont;


+ 33
- 0
frontend/src/components/shared/ReactHelmet.jsx Wyświetl plik

@@ -0,0 +1,33 @@
import { Helmet } from 'react-helmet-async';
import PropTypes from 'prop-types';
import '../../styles/cards.css';

const api_url = process.env.REACT_APP_API_URL;

const ReactHelmet = ({ seo }) => {
console.log(seo);
return (
<Helmet>
<title>{seo.metaTitle}</title>
<meta name="description" content={seo.metaDescription} />
<link rel="canonical" href={seo.canonicalURL} />
<meta name="keywords" content={seo.keywords} />
<meta name="viewport" content={seo.metaViewport} />
<meta name="robots" content={seo.metaRobots} />
<meta property="og:title" content={seo.metaSocial[0].title} />
<meta
property="og:image"
content={`${api_url}${seo.metaSocial[0].image.data.attributes.url}`}
/>
<meta property="og:description" content={seo.metaSocial[0].description} />
<meta property="twitter:title" content={seo.metaSocial[1].title} />
<meta
property="twitter:image"
content={`${api_url}${seo.metaSocial[1].image.data.attributes.url}`}
/>
<meta property="twitter:description" content={seo.metaSocial[1].description} />
</Helmet>
);
};

export default ReactHelmet;

+ 2
- 1
frontend/src/context/index.js Wyświetl plik

@@ -21,6 +21,7 @@ export const JobFormContext = React.createContext({
});

export const UIContext = React.createContext({
tab: '',
tab: true,
contactRef: '',
position: 0,
})

+ 10
- 13
frontend/src/hooks/useAnalytics.js Wyświetl plik

@@ -1,16 +1,13 @@
import React, { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { useEffect } from 'react';
import { useCookies } from 'react-cookie';
import ReactGA from 'react-ga4';

const useAnalytics = () => {
const location = useLocation();

useEffect(() => {
window.gtag('event', 'page_view', {
page_title: document.title,
page_path: location.pathname + location.search,
page_location: window.location.href
})
}, [location]);
}
const useAnalytics = pageTitle => {
const [cookies] = useCookies(['user']);
useEffect(() => {
if (cookies.diligent_ga === 'true')
ReactGA.send({ hitType: 'pageview', page: pageTitle });
}, []);
};

export default useAnalytics;

+ 17
- 0
frontend/src/hooks/useDataApi.js Wyświetl plik

@@ -38,6 +38,23 @@ const useDataApi = (initialUrl, initialData) => {
isError: false,
data: initialData,
});
//getData
useEffect(() => {
const fetchData = async () => {
dispatch({ type: 'FETCH_INIT' });
try {
const result = await axios(url);
dispatch({ type: 'FETCH_SUCCESS', payload: result.data.data.attributes });
} catch (error) {
dispatch({ type: 'FETCH_FAILURE' });
}
};
fetchData();
}, [url]);

useEffect(() => {
let didCancel = false;

+ 8
- 6
frontend/src/index.js Wyświetl plik

@@ -3,23 +3,25 @@ import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { CookiesProvider } from 'react-cookie';
import { BrowserRouter } from 'react-router-dom';
import { HelmetProvider } from 'react-helmet-async';

if (module.hot) module.hot.accept()

if (module.hot) module.hot.accept();

ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
<CookiesProvider>
<HelmetProvider>
<App />
</HelmetProvider>
</CookiesProvider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root'),
);



// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals

+ 35
- 3
frontend/src/pages/About.jsx Wyświetl plik

@@ -23,7 +23,9 @@ import Wrapper from '../layout/Wrapper';
import TimelineCardsWrapper2 from '../components/TimelineWrapper2';
import TimelineLogo from '../components/TimelineLogo';
import PageLayout from '../layout/PageLayout';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';
import ReactHelmet from '../components/shared/ReactHelmet';

const _data = {
heading: {
subheading: 'About Us',
@@ -185,16 +187,46 @@ const _data = {
},
};

const api_url = process.env.REACT_APP_API_URL;

export default function About() {
const [cnt, setCnt] = useState('');
const [isLoaded, setIsLoaded] = useState('');

useEffect(() => {
useEffect(async () => {
document.title = 'About Us';
var vid = document.getElementById('animation');
vid.playbackRate = 2;
await axios
.get(
`${api_url}/api/aboutpage?populate[0]=SEO&populate[1]=SEO.metaSocial&populate[2]=SEO.metaImage&populate[3]=SEO.metaSocial.image`,
)
.then(res => {
setCnt(res.data.data.attributes);
setIsLoaded(true);
})
.catch(err => {
console.log(err);
setIsLoaded(false);
});
}, []);

//useAnalytics();
useAnalytics('About Us');

if (!isLoaded) {
return (
<div className="z-50 w-full h-screen bg-white dark:bg-dg-primary-1700 dark:text-white flex items-center justify-center text-3xl font-semibold">
<video id="animation" width="540" height="540" autoPlay muted loop>
<source src={Animation_Diligent} type="video/webm" />
Loading...
</video>
</div>
);
}

return (
<PageLayout>
{cnt.SEO && <ReactHelmet seo={cnt.SEO} />}
<div className="bg-white dark:bg-dg-primary-1700 w-full pt-32">
{/* Heading Section */}
<section

+ 83
- 34
frontend/src/pages/Careers.jsx Wyświetl plik

@@ -1,9 +1,6 @@
import { useState, useEffect } from 'react';
import axios from 'axios';

import CardCareers from '../components/CardCareers';
import Contact from '../components/shared/Contact';

import Animation_Diligent from '../assets/animation_diligent.webm';
import Wrapper from '../layout/Wrapper';
import PageTitle from '../components/shared/PageTitle';
@@ -12,10 +9,10 @@ import CardValues from '../components/shared/CardValues';
import CardLife from '../components/shared/CardLife';
import ActionCard from '../components/shared/ActionCard';
import AboutUsSlider from '../components/shared/AboutUsSlider';
import CardCareers2 from '../components/CardCareers2';
import CardCareers2 from '../components/CareerCardsTemplates/CardCareers2';
import OrbitOnScroll from '../components/shared/graphics/OrbitOnScroll';
import PageLayout from '../layout/PageLayout';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';

// eslint-disable-next-line no-underscore-dangle
const _data = {
@@ -24,14 +21,83 @@ const _data = {
subheading: 'Careers',
},
job: {
cards: [
{
nugget: '.Net',
role: '.Net Developer',
shortDetails:
'An idea solves a problem. We help you to create that idea, build a product and scale it to be successful in your business.',
NetDev: {
id: 1,
templateFlag: 1,
role: '.Net Developer',
nugget: '.Net',
shortDetails:
'An idea solves a problem. We help you to create that idea, build a product and scale it to be successful in your business.',
extended: {
paragraph:
'Team Diligent is constantly growing! We are looking for a team player that will work with experienced engineers. If technology is your passion and you are ready to move the boundaries of your knowledge every day, then, Diligent is the right place for you. If you are not from Niš, we are offering a full remote position.',
requirements: [
'Good software development fundamentals and knowledge of .NET architecture concepts & patterns',
'Good knowledge of software design patterns',
'Good knowledge of databases and database design',
'Experience in working with microservices is a big plus',
'The ability to work in a big team but also to work independently',
'Excellent communication skills',
],
key: [
'Working as a full-stack developer on various project and products',
'Working with 3rd-party APIs',
'Working on different integration scenarios',
'Setting up project structure and architecture',
'Being involved in full project development, from writing a specification to deploying a finished product',
],
offer: [
'Full Remote position',
'A fast-growth company with stable projects and strong international clients',
'Opportunity to work in teams with experienced engineers',
'Competitive employment conditions',
'An environment that will make you feel good about your job',
'Challenging and diverse projects',
'Support in your personal and professional growth',
'Flexible working hours',
'Private health insurance',
],
},
],
},
// NetDevIntern: {
// id: 2,
// templateFlag: 2,
// role: '.Net Developer Internship',
// nugget: '.NetInernship',
// shortDetails:
// 'An idea solves a problem. We help you to create that idea, build a product and scale it to be successful in your business.',
// extended: {
// paragraph:
// 'Team Diligent is constantly growing! We are looking for a team player that will work with experienced engineers. If technology is your passion and you are ready to move the boundaries of your knowledge every day, then, Diligent is the right place for you. If you are not from Niš, we are offering a full remote position.',
// offer: [
// 'Paid internship',
// 'Full Remote position',
// 'A fast-growth company with stable projects and strong international clients',
// 'Experience of working in a team',
// 'Work on real project with real clients',
// 'Mentorship from industry leaders',
// 'Support in your personal and professional growth',
// 'Lots of team activities and perks',
// 'Modern working place with a positive and fun atmosphere',
// ],
// requirements: [
// 'Fundamentals of data structures ',
// 'Fundamentals and knowledge of .NET architecture concepts & patterns',
// 'Fundamentals of databases and database design',
// 'Team player and fast learner',
// 'Analytical and problem-solving skills',
// ],
// selectionProcess: [
// 'Application',
// 'CV Screening',
// 'HR Interview',
// 'Technical Interview',
// 'Internship - offer & contract',
// ],
// conslusionParagraph:
// 'At the end of the selection process, we will select interns able to join our team for a 3 months internship and arrange the beginning of the practice personally with you.',
// },
// },
},
life: {
heading: 'A Culture That’s Serious About Work and Fun',
@@ -93,13 +159,11 @@ export default function Careers({ forwardedRef }) {

const api_url = process.env.REACT_APP_API_URL;


useEffect(() => {
document.title = 'Careers';
}, []);

//useAnalytics();
useAnalytics('Careers');

useEffect(async () => {
var vid = document.getElementById('animation');
@@ -151,28 +215,11 @@ export default function Careers({ forwardedRef }) {
className="flex items-center justify-center max-w-custom m-auto"
>
<div className="w-full">
{/* {cntCareers.job.map(job => (
<div key={job.id}>
<CardCareers
image={job.icon.data.attributes.url}
heading={job.heading}
paragraph={job.paragraph}
requirements_heading={job.requirements_heading}
requirements_paragraph={job.requirements_paragraph}
expectations_heading={job.expectations_heading}
expectations_paragraph={job.expectations_paragraph}
benefits_heading={job.benefits_heading}
benefits_paragraph={job.benefits_paragraph}
hash_position={job.position}
setClickedPosition={setClickedPosition}
/>
</div>
))} */}
<CardCareers2 cards={_data.job.cards} />
<CardCareers2 cards={_data.job} />
</div>
</section>
</Wrapper>
<div className='mt-90p'>
<Wrapper bg padding={' py-90p'}>
<PageTitle
left
@@ -218,6 +265,8 @@ export default function Careers({ forwardedRef }) {
</section>
</div>
</Wrapper>
</div>
<Wrapper padding={' py-90p'}>
<PageTitle heading={_data.connect.heading} color />
<p className="paragraph my-32p">{_data.connect.paragraph}</p>

+ 141
- 140
frontend/src/pages/CaseStudy.jsx Wyświetl plik

@@ -1,5 +1,5 @@
import ActionCard from '../components/shared/ActionCard';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';
import PageLayout from '../layout/PageLayout';
import { useEffect } from 'react';

@@ -41,163 +41,164 @@ const technologies = [
export default function CaseStudy() {
useEffect(() => {
document.title = 'Case Studies';
},[]);
}, []);

useAnalytics('Case Studies');

//useAnalytics();
return (
<PageLayout>
<div className="bg-baby-blue dark:bg-dg-primary-1700 w-full pt-20 md:pt-24">
{/* Heading Section */}
<section
id="heading"
className="flex flex-col items-center justify-center m-auto py-16 md:py-32 bg-[url('https://images.unsplash.com/photo-1619252584172-a83a949b6efd')] bg-fixed bg-cover"
>
<div className="my-8 flex flex-col md:flex-row justify-start items-center w-full max-w-custom px-8 xl:px-0">
<div className="w-full">
<h6 className="subheading">Case Study</h6>
<h1 className="heading text-dg-secondary mt-2">BI Healthcare Solution </h1>
<p className="paragraph mt-4">
BI Solution that provides an uncommon level of insights into the healing
process.
</p>
<div className="bg-baby-blue dark:bg-dg-primary-1700 w-full pt-20 md:pt-24">
{/* Heading Section */}
<section
id="heading"
className="flex flex-col items-center justify-center m-auto py-16 md:py-32 bg-[url('https://images.unsplash.com/photo-1619252584172-a83a949b6efd')] bg-fixed bg-cover"
>
<div className="my-8 flex flex-col md:flex-row justify-start items-center w-full max-w-custom px-8 xl:px-0">
<div className="w-full">
<h6 className="subheading">Case Study</h6>
<h1 className="heading text-dg-secondary mt-2">BI Healthcare Solution </h1>
<p className="paragraph mt-4">
BI Solution that provides an uncommon level of insights into the healing
process.
</p>
</div>
</div>
</div>
</section>
</section>

{/* About the Client Section */}
<section id="client" className="flex flex-col items-center justify-center mt-16">
<div className="my-8 flex flex-col md:flex-row justify-center items-start w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full md:w-1/2">
<h3 className="h3-heading text-teal-600">About the Client</h3>
<p className="paragraph mt-4">
Healthcare company has a centralized IT solution for tracking every aspect
of their own business, especially services provided to clients and working
times of their clinicians in all clinics they own all around the USA.
</p>
</div>
<div className="w-full md:w-1/2 grid grid-cols-2 md:grid-cols-3 gap-16 mt-8 md:mt-0">
<div className="hidden md:inline-block"></div>
<div className="float-left md:float-right text-left md:text-right">
<h5 className="text-teal-600 font-semibold">Country</h5>
<p className="mt-4">USA</p>
{/* About the Client Section */}
<section id="client" className="flex flex-col items-center justify-center mt-16">
<div className="my-8 flex flex-col md:flex-row justify-center items-start w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full md:w-1/2">
<h3 className="h3-heading text-teal-600">About the Client</h3>
<p className="paragraph mt-4">
Healthcare company has a centralized IT solution for tracking every aspect
of their own business, especially services provided to clients and working
times of their clinicians in all clinics they own all around the USA.
</p>
</div>
<div className="float-left md:float-right text-left md:text-right">
<h5 className="text-teal-600 font-semibold">Industry</h5>
<p className="mt-4">Healthcare</p>
<div className="w-full md:w-1/2 grid grid-cols-2 md:grid-cols-3 gap-16 mt-8 md:mt-0">
<div className="hidden md:inline-block"></div>
<div className="float-left md:float-right text-left md:text-right">
<h5 className="text-teal-600 font-semibold">Country</h5>
<p className="mt-4">USA</p>
</div>
<div className="float-left md:float-right text-left md:text-right">
<h5 className="text-teal-600 font-semibold">Industry</h5>
<p className="mt-4">Healthcare</p>
</div>
</div>
</div>
</div>
</section>

{/* Domain Section */}
<section id="domain" className="flex flex-col items-center justify-center mt-16">
<div className="my-8 flex flex-col justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading">Domain</h3>
<p className="paragraph mt-4">
BI Solution helps clinicians to improve their work and create a wider
picture of client progress during the healing process. The solution offers
our customers a high level of insight into their cash flows and workforce
organization. In one word, this is a fully customizable solution for a
comprehensive business process.
</p>
</div>
</div>
</section>
</section>

{/* Challanges, Solution Section */}
<section
id="challanges_solution"
className="flex flex-col items-center justify-center mt-16"
>
<div className="my-8 flex flex-col md:flex-row justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full md:w-1/2 md:pr-16">
<div>
<h3 className="h3-heading">Challanges</h3>
<p className="text-sm text-dark-gray dark:text-white mt-4">
The main objective is to create a solution that meets the requirements of
stakeholders while integrating with existing IT systems to get data
without impacting the system. The solution should use only an MS stack of
technologies while taking care of sensitive data, and maintaining and
providing up-to-date data. The solution should also be a comfortable and
reliable, user-friendly solution for everyday work.
</p>
</div>
<div className="mt-8">
<h3 className="h3-heading">Solution</h3>
<p className="text-sm text-dark-gray dark:text-white mt-4">
The purpose of interactive data visualization is to allow users to explore
and understand data. We used the Power BI analytics service to accomplish
this. Azure has several features that automate data processing and ensure
the reliability and security of the data.
{/* Domain Section */}
<section id="domain" className="flex flex-col items-center justify-center mt-16">
<div className="my-8 flex flex-col justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading">Domain</h3>
<p className="paragraph mt-4">
BI Solution helps clinicians to improve their work and create a wider
picture of client progress during the healing process. The solution offers
our customers a high level of insight into their cash flows and workforce
organization. In one word, this is a fully customizable solution for a
comprehensive business process.
</p>
</div>
</div>
<img
src="https://drive.google.com/uc?export=view&id=1TDOQDUkH4dDnjx2x5DJkDpi5xEHrbCvS"
alt="Case Study main image"
className="text-center w-full md:w-1/2"
/>
</div>
</section>
</section>

{/* Results Section */}
<section id="results" className="flex flex-col items-center justify-center mt-16">
<div className="my-8 flex flex-col justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading text-dg-secondary">Results</h3>
<ul className="list-disc paragraph mt-2 pl-8">
<li>Visualize information to ensure better data understanding </li>
<li>
Deliver the product within an established amount of time and defined
budgets
</li>
<li> Be up to date with the latest stack of technologies</li>
<li>
Offer services from ETL with complex data processing to data visualization
</li>
</ul>
{/* Challanges, Solution Section */}
<section
id="challanges_solution"
className="flex flex-col items-center justify-center mt-16"
>
<div className="my-8 flex flex-col md:flex-row justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full md:w-1/2 md:pr-16">
<div>
<h3 className="h3-heading">Challanges</h3>
<p className="text-sm text-dark-gray dark:text-white mt-4">
The main objective is to create a solution that meets the requirements
of stakeholders while integrating with existing IT systems to get data
without impacting the system. The solution should use only an MS stack
of technologies while taking care of sensitive data, and maintaining and
providing up-to-date data. The solution should also be a comfortable and
reliable, user-friendly solution for everyday work.
</p>
</div>
<div className="mt-8">
<h3 className="h3-heading">Solution</h3>
<p className="text-sm text-dark-gray dark:text-white mt-4">
The purpose of interactive data visualization is to allow users to
explore and understand data. We used the Power BI analytics service to
accomplish this. Azure has several features that automate data
processing and ensure the reliability and security of the data.
</p>
</div>
</div>
<img
src="https://drive.google.com/uc?export=view&id=1TDOQDUkH4dDnjx2x5DJkDpi5xEHrbCvS"
alt="Case Study main image"
className="text-center w-full md:w-1/2"
/>
</div>
</div>
</section>
</section>

{/* Technologies Section */}
<section
id="technologies"
className="flex flex-col items-center justify-center mt-16"
>
<div className="my-8 flex flex-col justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading">Technologies</h3>
{/* Results Section */}
<section id="results" className="flex flex-col items-center justify-center mt-16">
<div className="my-8 flex flex-col justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading text-dg-secondary">Results</h3>
<ul className="list-disc paragraph mt-2 pl-8">
<li>Visualize information to ensure better data understanding </li>
<li>
Deliver the product within an established amount of time and defined
budgets
</li>
<li> Be up to date with the latest stack of technologies</li>
<li>
Offer services from ETL with complex data processing to data
visualization
</li>
</ul>
</div>
</div>
<div className="grid grid-cols-4 justify-center justify-items-center gap-8 xl:flex xl:flex-row items-center xl:justify-start xl:gap-16 w-full mt-8">
{technologies.map(technology => (
<img
key={technology.id}
src={technology.link}
alt="Technology's image"
className="w-12 md:w-16 lg:w-20"
/>
))}
</section>

{/* Technologies Section */}
<section
id="technologies"
className="flex flex-col items-center justify-center mt-16"
>
<div className="my-8 flex flex-col justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading">Technologies</h3>
</div>
<div className="grid grid-cols-4 justify-center justify-items-center gap-8 xl:flex xl:flex-row items-center xl:justify-start xl:gap-16 w-full mt-8">
{technologies.map(technology => (
<img
key={technology.id}
src={technology.link}
alt="Technology's image"
className="w-12 md:w-16 lg:w-20"
/>
))}
</div>
</div>
</div>
</section>
</section>

{/* CTA Section */}
<section id="cta" className="flex flex-col items-center justify-center mt-16">
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}
link2={'/contact'}
/>
</div>
</section>
</div>
{/* CTA Section */}
<section id="cta" className="flex flex-col items-center justify-center mt-16">
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Grow faster with a dedicated team of .NET & JS experts."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}
link2={'/contact'}
/>
</div>
</section>
</div>
</PageLayout>
);
}

+ 13
- 5
frontend/src/pages/CaseStudyBI.jsx Wyświetl plik

@@ -10,7 +10,7 @@ import { useEffect } from 'react';
import Wrapper from '../layout/Wrapper';
import TechNuggets from '../components/shared/TechNuggets';
import { motion } from 'framer-motion';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';

const numbers = [
{
@@ -117,12 +117,11 @@ const _data = {
};

export default function CaseStudyBI() {
useEffect(() => {
document.title = 'Case Study: BI Healthcare Solution';
}, []);

//useAnalytics();
useAnalytics('Case Study: BI Healthcare Solution');

return (
<PageLayout>
@@ -245,7 +244,16 @@ export default function CaseStudyBI() {
<h3 className="h3-heading">Technologies</h3>
</div>
<TechNuggets
tech={['Azure Data Factory','Azure SQL Server', 'Microsoft Power BI', '.Net Core', 'Azure App Services', 'Microsoft Power Automate','Azure Logic Apps','Azure Active Directory']}
tech={[
'Azure Data Factory',
'Azure SQL Server',
'Microsoft Power BI',
'.Net Core',
'Azure App Services',
'Microsoft Power Automate',
'Azure Logic Apps',
'Azure Active Directory',
]}
/>
</div>
</section>
@@ -255,7 +263,7 @@ export default function CaseStudyBI() {
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product."
text="Grow faster with a dedicated team of .NET & JS experts."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}

+ 24
- 26
frontend/src/pages/CaseStudyCentralized.jsx Wyświetl plik

@@ -10,7 +10,7 @@ import { useEffect } from 'react';
import Wrapper from '../layout/Wrapper';
import { motion } from 'framer-motion';
import TechNuggets from '../components/shared/TechNuggets';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';

const numbers = [
{
@@ -58,7 +58,7 @@ const _data = {
challanges: {
heading: 'Challanges',
paragraph:
"Some of them didn't even have open API-s, some of them required an extra set of rules, and some of them were still in development. This made integration difficult and time-consuming. However, we were eventually able to overcome these challenges and provide our users with a seamless experience.",
"Some of our biggest challenges were connected with the actual diversity of systems that we needed to integrate. Some of them didn't even have open API-s, some required an extra set of rules, and some were still in development. This made integration difficult and time-consuming. However, we were eventually able to overcome these challenges and provide our users with a seamless experience.",
},

solution: {
@@ -120,12 +120,11 @@ const _data = {
};

export default function CaseStudyCentralized() {
useEffect(() => {
document.title = 'Case Study: Centralized Monitoring System';
}, []);

//useAnalytics();
useAnalytics('Case Study: Centralized Monitoring System');

return (
<PageLayout>
@@ -146,26 +145,25 @@ export default function CaseStudyCentralized() {
</div>
</section>

<Wrapper padding={' py-90p'}>
<motion.section
id="status-numbers"
className="flex flex-col md:flex-row items-start justify-between w-full gap-90p px-90p"
initial={{ y: 60, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, ease: 'easeOut' }}
>
{numbers.map((item, i) => (
<div key={i} className="flex flex-col">
<h2 className="display-number text-center">
{item.value}{item.static}
</h2>
<h3 className="number-title text-center">
{item.title}
</h3>
</div>
))}
</motion.section>
</Wrapper>
<Wrapper padding={' py-90p'}>
<motion.section
id="status-numbers"
className="flex flex-col md:flex-row items-start justify-between w-full gap-90p px-90p"
initial={{ y: 60, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, ease: 'easeOut' }}
>
{numbers.map((item, i) => (
<div key={i} className="flex flex-col">
<h2 className="display-number text-center">
{item.value}
{item.static}
</h2>
<h3 className="number-title text-center">{item.title}</h3>
</div>
))}
</motion.section>
</Wrapper>

{/* About the Client Section */}
<section id="client" className="flex flex-col items-center justify-center mt-16">
@@ -250,7 +248,7 @@ export default function CaseStudyCentralized() {
<div className="w-full">
<h3 className="h3-heading">Technologies</h3>
</div>
<TechNuggets tech={['.Net','MS SQL Server','JQuery','Power BI']} />
<TechNuggets tech={['.Net', 'MS SQL Server', 'JQuery', 'Power BI']} />
</div>
</section>

@@ -259,7 +257,7 @@ export default function CaseStudyCentralized() {
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product."
text="Grow faster with a dedicated team of .NET & JS experts."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}

+ 12
- 6
frontend/src/pages/CaseStudyFinantial.jsx Wyświetl plik

@@ -8,7 +8,7 @@ import { useEffect } from 'react';
import { motion } from 'framer-motion';
import Wrapper from '../layout/Wrapper';
import TechNuggets from '../components/shared/TechNuggets';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';
const numbers = [
{
value: 5,
@@ -113,7 +113,7 @@ export default function CaseStudyFinantial() {
document.title = 'Case Study: Financial Engine';
}, []);

//useAnalytics();
useAnalytics('Case Study: Financial Engine');

return (
<PageLayout>
@@ -229,14 +229,20 @@ export default function CaseStudyFinantial() {
</div>
</section>

{/* Technologies Section */}
<section id="technologies" className="flex flex-col mt-16">
{/* Technologies Section */}
<section id="technologies" className="flex flex-col mt-16">
<div className="my-8 flex flex-col w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading">Technologies</h3>
</div>
<TechNuggets
tech={['.Net','Service-Oriented Architecture (SOA)', 'MS SQL Server', 'MS MVC', 'Event-Driven Architecture (EDA)']}
tech={[
'.Net',
'Service-Oriented Architecture (SOA)',
'MS SQL Server',
'MS MVC',
'Event-Driven Architecture (EDA)',
]}
/>
</div>
</section>
@@ -246,7 +252,7 @@ export default function CaseStudyFinantial() {
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product."
text="Grow faster with a dedicated team of .NET & JS experts."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}

+ 4
- 8
frontend/src/pages/CaseStudyResource.jsx Wyświetl plik

@@ -10,7 +10,7 @@ import { useEffect } from 'react';
import { motion } from 'framer-motion';
import Wrapper from '../layout/Wrapper';
import TechNuggets from '../components/shared/TechNuggets';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';

const numbers = [
{
@@ -115,13 +115,11 @@ const _data = {
};

export default function CaseStudyResource() {


useEffect(() => {
document.title = 'Case Study: Resource Planning System';
}, []);

//useAnalytics();
useAnalytics('Case Study: Resource Planning System');

return (
<PageLayout>
@@ -243,9 +241,7 @@ export default function CaseStudyResource() {
<div className="w-full">
<h3 className="h3-heading">Technologies</h3>
</div>
<TechNuggets
tech={['.Net', 'MS SQL Server', 'React Native', 'React.JS']}
/>
<TechNuggets tech={['.Net', 'MS SQL Server', 'React Native', 'React.JS']} />
</div>
</section>

@@ -254,7 +250,7 @@ export default function CaseStudyResource() {
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product."
text="Grow faster with a dedicated team of .NET & JS experts."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}

+ 5
- 8
frontend/src/pages/CaseStudyStrata.jsx Wyświetl plik

@@ -11,7 +11,7 @@ import { useEffect } from 'react';
import { motion } from 'framer-motion';
import Wrapper from '../layout/Wrapper';
import TechNuggets from '../components/shared/TechNuggets';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';

const numbers = [
{
@@ -111,13 +111,12 @@ const _data = {
};

export default function CaseStudyStrata() {

useEffect(() => {
document.title = 'Case Study: Healthcare Tracking Software';
}, []);

//useAnalytics();
useAnalytics('Case Study: Healthcare Tracking Software');
return (
<PageLayout>
<div className="bg-baby-blue dark:bg-dg-primary-1700 w-full pt-20 md:pt-24">
@@ -240,9 +239,7 @@ export default function CaseStudyStrata() {
<div className="w-full">
<h3 className="h3-heading">Technologies</h3>
</div>
<TechNuggets
tech={['C#', 'MVC', 'SQL','Ajax','React Native']}
/>
<TechNuggets tech={['C#', 'MVC', 'SQL', 'Ajax', 'React Native']} />
</div>
</section>

@@ -251,7 +248,7 @@ export default function CaseStudyStrata() {
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product."
text="Grow faster with a dedicated team of .NET & JS experts."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}

+ 6
- 11
frontend/src/pages/CaseStudyTicketing.jsx Wyświetl plik

@@ -10,7 +10,7 @@ import ionic from './../assets/icons/caseStudy/ionic.svg';
import { useEffect } from 'react';
import { motion } from 'framer-motion';
import TechNuggets from '../components/shared/TechNuggets';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';
const numbers = [
{
value: 10,
@@ -57,7 +57,7 @@ const _data = {
challanges: {
heading: 'Challanges',
paragraph:
'There are many different types of applications based on a platform where they will be executed. There is a lot of specific hardware system (ex. Cameras, Barcode scanner, etc.) that needed to be connected with some parts of our system. Data between components must be shared in real-time.',
'There are many different types of applications based on a platform where they will be executed. There are a lot of specific hardware systems (ex. Cameras, Barcode scanner, etc.) that needed to be connected with some parts of our system. Data between components must be shared in real-time.',
},

solution: {
@@ -73,7 +73,7 @@ const _data = {
list: [
{
id: 1,
text: 'Uploading documents for every case and for every hearing',
text: 'Innovations introduced with the latest hardware in the industry',
},
{
id: 2,
@@ -123,13 +123,11 @@ const _data = {
};

export default function CaseStudyTicketing() {

useEffect(() => {
document.title = 'Case Study: Ticketing System For Passengers';
}, []);

//useAnalytics();
useAnalytics('Case Study: Ticketing System For Passengers');

return (
<PageLayout>
@@ -246,10 +244,7 @@ export default function CaseStudyTicketing() {
</section>

{/* Technologies Section */}
<section
id="technologies"
className="flex flex-col mt-16"
>
<section id="technologies" className="flex flex-col mt-16">
<div className="my-8 flex flex-col w-full max-w-custom m-auto px-8 xl:px-0">
<div className="w-full">
<h3 className="h3-heading">Technologies</h3>
@@ -265,7 +260,7 @@ export default function CaseStudyTicketing() {
<div className="px-8 mt-8 mb-32 w-full max-w-custom">
<ActionCard
title="Let's Work Together!"
text="Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product."
text="Grow faster with a dedicated team of .NET & JS experts."
btn1="More Projects"
btn2="Contact Us"
link1={'/portfolio'}

+ 8
- 4
frontend/src/pages/ContactPage.jsx Wyświetl plik

@@ -1,22 +1,26 @@
import React, { useEffect, useState } from 'react';
import Contact from '../components/shared/Contact';
import { UIContext } from '../context';
import PageLayout from '../layout/PageLayout';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';

function ContactPage() {
const [data, setData] = useState('');
const [isLoaded, setIsLoaded] = useState('');


useEffect(() => {
document.title = 'Contact Us';
}, []);

useAnalytics('Contact Us');

return (
<PageLayout>
<section id="contact" className="h-fit bg-baby-blue dark:bg-dg-primary-1600 mt-90p">
<h1 className="hidden">Contact us: Tell Us about Your Idea!</h1>
<Contact defaultIndex={0} />
<UIContext.Provider value={UIContext}>
<Contact />
</UIContext.Provider>
</section>
</PageLayout>
);

+ 22
- 3
frontend/src/pages/Home.jsx Wyświetl plik

@@ -30,8 +30,23 @@ import PortfolioSection from '../components/PortfolioSection';
import PageLayout from '../layout/PageLayout';
import MapDilig from '../components/Map';
import useDataApi from '../hooks/useDataApi';
import useAnalytics from '../hooks/useAnalytics';
import ReactHelmet from '../components/shared/ReactHelmet';

const api_url = process.env.REACT_APP_API_URL;
// const fieldArray = [
// 'landing',
// 'why',
// 'why.heading',
// 'why.card_left.icon',
// 'why.card_mid.icon',
// 'why.card_right.icon',
// 'landing.heading',
// 'SEO',
// 'SEO.metaSocial',
// 'SEO.metaImage',
// 'SEO.metaSocial.image',
// ];


const strapiPopulate = [
@@ -59,7 +74,7 @@ const stringBuilder = () => {
return stringQuery;
};

export default function Home({forwardedRef}) {
export default function Home({ forwardedRef }) {
const [cnt, setCnt] = useState('');
const [landingData, setLandingData] = useState(null);
const [cardData, setCardData] = useState(null);
@@ -69,6 +84,9 @@ export default function Home({forwardedRef}) {
const [{ data, isLoading, isError }, doFetch] = useDataApi(
`${api_url}/api/w-home-page?${stringBuilder()}`,
);
const [contactElement, setContactElement] = useState(0);

useAnalytics('Home page');

useEffect(() => {
document.title = 'Diligent Software';
@@ -115,6 +133,7 @@ export default function Home({forwardedRef}) {
} else {
return (
<PageLayout>
{cnt.SEO && <ReactHelmet seo={cnt.SEO} />}
<div className="bg-white dark:bg-dg-primary-1700 w-full pt-32 overflow-hidden">
{/* <FormSwitch /> */}

@@ -130,10 +149,10 @@ export default function Home({forwardedRef}) {
</Tab.Group> */}

{/* Landing Section */}
{data && <Landing heading={data.Heading} numbers={data.HeroNumbers.number} button={data.button} paragraph={data.paragraph} />}
<Landing data={cnt.landing.heading} />

{/* Why Us Section */}
{data && <WhySection heading={data.WhyUsHeading} cards={data.Cards} p1={data.WhyUsParagraph1} p2={data.WhyUsParagraph2} />}
<WhySection data={cnt.why} />

{/* Our Services Section */}
{/* <ServicesHome /> */}

+ 34
- 3
frontend/src/pages/Portfolio.jsx Wyświetl plik

@@ -13,7 +13,8 @@ import CardsGrid from '../components/CardsGrid';
import PageLayout from '../layout/PageLayout';

import StrataThumb from './../assets/images/CaseStudy/StrataThumb.jpg';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';
import ReactHelmet from '../components/shared/ReactHelmet';

const _data = {
heading: {
@@ -73,16 +74,46 @@ const _data = {
],
};

const api_url = process.env.REACT_APP_API_URL;

export default function Portfolio() {
const [cnt, setCnt] = useState('');
const [isLoaded, setIsLoaded] = useState('');

useEffect(() => {
useEffect(async () => {
document.title = 'Case Studies';
var vid = document.getElementById('animation');
vid.playbackRate = 2;
await axios
.get(
`${api_url}/api/portfoliopage?populate[0]=SEO&populate[1]=SEO.metaSocial&populate[2]=SEO.metaImage&populate[3]=SEO.metaSocial.image`,
)
.then(res => {
setCnt(res.data.data.attributes);
setIsLoaded(true);
})
.catch(err => {
console.log(err);
setIsLoaded(false);
});
}, []);

//useAnalytics();
useAnalytics('Case Studies');

if (!isLoaded) {
return (
<div className="z-50 w-full h-screen bg-white dark:bg-dg-primary-1700 dark:text-white flex items-center justify-center text-3xl font-semibold">
<video id="animation" width="540" height="540" autoPlay muted loop>
<source src={Animation_Diligent} type="video/webm" />
Loading...
</video>
</div>
);
}

return (
<PageLayout>
{cnt.SEO && <ReactHelmet seo={cnt.SEO} />}
<div className="flex flex-col gap-90p pt-32">
<Wrapper>
<h1 className="hidden">Our Work - Case Studies</h1>

+ 7
- 10
frontend/src/pages/ProcessPage.jsx Wyświetl plik

@@ -16,7 +16,7 @@ import PageLayout from '../layout/PageLayout';
import ProcessFacelessSlider from '../components/shared/ProcessFacelessSlider';
import useWindowSize from '../hooks/useWindowSize';
import ProcessSlider from '../components/ProcessSlider';
//import useAnalytics from '../hooks/useAnalytics';
import useAnalytics from '../hooks/useAnalytics';

const _data = {
heading: {
@@ -115,14 +115,13 @@ const _data = {
ActionCard: {
heading: 'Let’s Work Together!',
paragraph:
'Business Intelligence portal which enhouses series of web applications & reporting tools used for in-depth analysis on product pricing, money flow, resources, employees, etc. Applications provide administrative users overview, as well as detail look scaled down to individual product.',
'Grow faster with a dedicated team of .NET & JS experts.',
primaryBtn: 'Contact Us',
secondaryBtn: 'Portfolio',
},
};

const ProcessPage = () => {

const [isMobile, setIsMobile] = useState(false);

const windowInfo = useWindowSize();
@@ -131,14 +130,12 @@ const ProcessPage = () => {
document.title = 'Process';
}, []);

//useAnalytics();
useAnalytics('Process');

useEffect(() => {
if (windowInfo.width < 1000)
setIsMobile(true);
else
setIsMobile(false);
},[windowInfo]);
if (windowInfo.width < 1000) setIsMobile(true);
else setIsMobile(false);
}, [windowInfo]);

return (
<PageLayout>
@@ -160,7 +157,7 @@ const ProcessPage = () => {
</div> */}
<div className="relative mx-auto my-32p md:my-90p">
{!isMobile ? (
<div className="w-full">
<div className="flex w-full">
<ProcessSvg className="" />
</div>
) : (

+ 257
- 199
frontend/src/pages/WorkWithUs.jsx Wyświetl plik

@@ -1,219 +1,277 @@
import React, { Children, useEffect } from 'react'
import { Link } from 'react-router-dom'
import CustomLink from '../components/root/CustomLink'
import TertiaryButton from '../components/root/TertiaryButton'
import ActionCard from '../components/shared/ActionCard'
import CardLife from '../components/shared/CardLife'
import PageHeading from '../components/shared/PageHeading'
import PageTitle from '../components/shared/PageTitle'
import Testimonials from '../components/Testimonials'
//import useAnalytics from '../hooks/useAnalytics'
import Wrapper from '../layout/Wrapper'
import {ReactComponent as DownalodIcon } from './../assets/download-icon.svg'
import {ReactComponent as BusIcon } from './../assets/icons/workwithus/bus.svg'
import {ReactComponent as FintechIcon } from './../assets/icons/workwithus/empty-wallet-tick.svg'
import {ReactComponent as HospitalIcon } from './../assets/icons/workwithus/hospital.svg'
import {ReactComponent as SchoolIcon } from './../assets/icons/workwithus/teacher.svg'
import React, { Children, Fragment, useEffect } from 'react';
import CustomLink from '../components/root/CustomLink';
import ActionCard from '../components/shared/ActionCard';

const _data = {
downloadIcon: '',
downloadFilePath: `${process.env.PUBLIC_URL}/DiligentCompanyOverview.pdf`,
downloadFileName: 'Diligent Company Overview.pdf',
problems: [
{
id:1,
title:'Lack of dedication and long-term commitment',
paragraph:'More often than not, our clients come to realize that the only familiar face they see from the company to which they outsource is the account manager. Technical staff fluctuates, hampering team cohesion, and preventing meaningful progress and team growth - there’s little valuable knowledge accumulation in the team.'
},
{
id:2,
title:'Resources are unable to scale with what the company needs',
paragraph:'Dynamic of the business environment demands from our clients the ability to perform a fast-paced scale up and down of their tech teams. The delays introduced due to lack of available resources, or lack of appropriate resources, prolong the development process or stop it altogether. Inability to quickly scale down impacts the budget, flexibility in responding to unforeseen market conditions, and fast repurposing of resources. ',
},
{
id:3,
title:'Lack of quality tech-staff that wouldn’t break a bank',
paragraph:'Our clients are unable to onboard enough high-quality tech resources to cover all their needs . The two main reasons for this are lack of available high-quality resources and the cost of those resources.',
}
],
help: [
{
id:1,
title:'We outsource for a company, not a project',
paragraph:'All of our resources are dedicated to a single client. We provide the conditions, and expect them to put all their focus into understanding the whole of the client’s business - from high level to the details. This approach allows for knowledge accumulation and increase in value of their contribution with time.'
},
{
id:2,
title:'Long term, dedicated engineers',
paragraph:'Related to the previous point, our relationships with the clients tend to be very long-term. We have, where the relationship was long enough, the same resources onboarded with the same client for more than a decade. Our resources are more a part of the client’s company then they are of Diligent - Diligent is just the venue allowing them to do their job. ',
},
{
id:3,
title:'Jump right in - we know our domains',
paragraph:'Diligent’s resources, in business domains where we have accumulated experience, are capable of quickly producing high-value contributions to our clients. We know the concepts, we are familiar with the processes, we’ve faced the problems and solved them. If faced with something new - we’ll learn and do it quickly.'
},
{
id:4,
title:'Competitive prices',
paragraph:'Diligent provides a low entry price for our new clients until proven as a valuable partner. Even afterwards, once we’ve shown what we can do and contribute meaningfully to our client’s business, we tend to operate with lower fees than our competitors. Simply ask us for a bid or a pricing table and we’ll show you.'
}
]
import useDataApi from '../hooks/useDataApi';
import Animation_Diligent from '../assets/animation_diligent.webm';
import Wrapper from '../layout/Wrapper';

import PageLayout from '../layout/PageLayout';
import PageTitleOneFont from '../components/shared/PageTitleOneFont';
import GradientWrapper from '../components/shared/GradientWrapper';

import '../App.css';
import useAnalytics from './../hooks/useAnalytics';

const api_url = process.env.REACT_APP_API_URL;

const download = {
downloadFilePath: `${process.env.PUBLIC_URL}/DiligentCompanyOverview.pdf`,
downloadFileName: 'Diligent Company Overview.pdf',
};

const Segment = ({children}) => {
return (
<div className='py-[48px] mx-auto w-full text-center'>
{children}
</div>
);
}
const strapiPopulate = [
'Heading',
'Heading.subtitle',
'Heading.title',
'Problems',
'Highlighted',
'Highlighted.title',
'Highlighted.paragraph',
'WhyWork',
'WhyWork.img',
'Stats',
'SucessParagraph',
'Spec',
'Download',
'OfficeImg',
'WorkTogether',
];

const TechCard = ({children}) => {
return (
<div className='rounded-[8px] bg-white py-[24px] px-[32px] items-center justify-center text-center'>
{children}
</div>
)
}
const HelpParagraph = ({title, paragraph}) => {
const stringBuilder = () => {
let stringQuery = '';
strapiPopulate.map((item, index) => {
if (index !== 0) stringQuery += '&';
stringQuery += `populate=${item}`;
});
return stringQuery;
};

const NumberIcon = ({ number }) => {
return (
<div>
<h4 className='font-semibold text-title'>{title}</h4>
<p>{paragraph}</p>
<div className="bg-baby-blue rounded-[6px] h-[48px] w-[48px] flex justify-center items-center text-center font-semibold text-dg-primary-900 text-n-h3-heading-mobile md:n-h3-heading">
<h4>{number}.</h4>
</div>
)
}
);
};

const WorkWithUs = () => {
//useAnalytics();
useAnalytics('Work With Us');

const [{ data, isLoading, isError }, doFetch] = useDataApi(
`${api_url}/api/work-with-us-page?${stringBuilder()}`,
);

useEffect(() => {
document.title = 'Work With Us';
},[]);
}, []);

return (
<div className='mt-90p'>
<Wrapper padding={' py-[48px]'}>
<PageTitle heading={'Diligent at a Glance'} subheading={'work with us'} />
</Wrapper>
<div className='flex flex-col md:flex gap-[32px] w-fit mx-auto'>
<CustomLink href={_data.downloadFilePath} downloadFile={_data.downloadFileName} context={'Company Overview'}>
<p>Company Overview</p>
<DownalodIcon/>
</CustomLink>
</div>
<Segment>
<p>Our clients primarily come from one of the following 4 business domains:</p>
</Segment>
<Wrapper bg padding={' py-[48px]'}>
<div className='flex grid grid-cols-2 lg:grid-cols-4 gap-32p items-center justify-center mx-auto'>
<TechCard>
<FintechIcon className='mx-auto'/>
<p>Fintech</p>
</TechCard>
<TechCard>
<HospitalIcon className='mx-auto'/>
<p>Healthcare</p>
</TechCard>
<TechCard>
<BusIcon className='mx-auto'/>
<p>Transportation</p>
</TechCard>
<TechCard>
<SchoolIcon className='mx-auto'/>
<p>Education</p>
</TechCard>
</div>
</Wrapper>
<Wrapper padding={' py-[48px]'}>
<p className='pb-32p max-w-[1000px] mx-auto'>Within those domains, our customers range from startups (11.2 Ventures), over small and medium sized companies (Gold Bullion International, Intellum…), to Fortune 500 companies (Henry Schein…).</p>
<p className='max-w-[1000px] mx-auto'>Decision to outsource the whole, or a part, of software development accompanied with a demand for personal, long-term, dedication and responsibility is common for our clients. Most of them have already had some experience with other outsourcing companies, or are in active relationships with other outsourcing companies, when they decide to give us a try.</p>
</Wrapper>
<Wrapper padding={' py-[48px]'}>
<h4 className='font-semibold font-secondary text-[#9B32CE] text-subtitle-48 text-center w-full'>What Are Their Problems?</h4>
</Wrapper>
<Wrapper >
<section>
<div className="flex flex-col justify-center items-start w-full max-w-custom m-auto px-8 xl:px-0 mb-[90px]">
<div className="flex flex-col gap-32p w-full max-w-[950px] mx-auto">
{_data.problems.map((item, index) => (
<CardLife
key={index}
number={item.id}
heading={item.title}
paragraph={item.paragraph}
/>
if (isLoading) {
return (
<div className="z-50 w-full h-screen bg-white dark:bg-dg-primary-1700 overflow-hidden dark:text-white flex items-center justify-center text-3xl font-semibold">
<video id="animation" width="540" height="540" autoPlay muted loop>
<source src={Animation_Diligent} type="video/webm" />
Loading...
</video>
</div>
);
} else {
return (
<PageLayout>
<div className="mt-[48px] md:mt-[180px]">
<Wrapper padding={' py-[48px]'}>
{data ? (
<Fragment>
<PageTitleOneFont
heading={data.Heading.title}
subheading={data.Heading.subtitle}
left
/>
<p className="mt-[16px] mr-0 md:mr-[400px] n-paragraph">
{data.HeadingParagraph}
</p>
</Fragment>
) : null}
</Wrapper>
<div className="mx-auto md:mx-2/5 pb-90p">
<Wrapper padding={' md:py-[48px]'}>
{data ? (
<h2 className="n-h3-heading md:text-center">{data.ProblemsTitle}</h2>
) : null}
</Wrapper>

<Wrapper padding={' py-[48px]'}>
{data ? (
<div className="flex flex-col gap-90p max-w-[860px] mx-auto">
{data.Problems.map((item, index) => (
<div key={index} className="flex flex-col md:flex-row gap-[32px]">
<div>
<NumberIcon number={index + 1} />
</div>
<div className="flex flex-col gap-[4px]">
<h6 className="n-paragraph-title">{item.title}</h6>
<p className="n-paragraph">{item.paragraph}</p>
</div>
</div>
))}
</div>
) : null}
</Wrapper>
</div>
{data ? (
<GradientWrapper padding={'py-32p md:py-90p'}>
<h6 className="n-h3-heading text-white">{data.Highlighted.title}</h6>
<p className="n-paragraph text-white md:max-w-[800px] mx-0 md:mx-auto">
{data.Highlighted.paragraph}
</p>
</GradientWrapper>
) : null}
{data ? (
<Wrapper padding={' py-[32px] md:py-[200px]'}>
<div className="flex flex-col gap-[64px] md:gap-[120px]">
{data.WhyWork.map((item, index) => (
<div
key={index}
className={
(index % 2
? 'flex flex-col md:flex-row-reverse '
: 'flex flex-col md:flex-row ') +
'w-full justify-between items-center gap-[24px] md:gap-0'
}
>
<div>
<img src={api_url + item.img.data.attributes.url}></img>
</div>
<div className="flex flex-col gap-[8px] md:gap-[16px] max-w-[520px]">
<h6 className="n-h3-heading text-dark-gray">{item.title}</h6>
<p className="n-paragraph">{item.paragraph}</p>
</div>
</div>
))}
</div>
</Wrapper>
) : null}
{data ? (
<GradientWrapper padding={'py-32p md:py-90p'}>
<div className="max-w-custom flex flex-col md:flex-row md:justify-between gap-[64px] md:gap-0">
{data.Stats.map((item, index) => (
<div key={index} className="flex flex-col gap-[8px] text-center">
<h6 className="n-heading text-white">{item.value}</h6>
<p className="n-paragraph-title text-white">{item.title}</p>
</div>
))}
</div>
</GradientWrapper>
) : null}
<Wrapper padding={' py-[48px] md:py-[200px]'}>
{data ? (
<div className="flex flex-col gap-[16px]">
<h6 className="n-h3-heading text-dark-gray">{data.SuccessTitle}</h6>
{data.SucessParagraph.map((item, index) => (
<p key={index} className="n-paragraph">
{item.ParagraphElement}
</p>
))}
</div>
) : null}
</Wrapper>
<div className="mx-auto md:mx-2/5 pb-90p">
<Wrapper padding={' md:py-[48px]'}>
{data ? (
<h6 className="n-h3-heading md:text-center text-dark-gray">
{data.SpecTitle}
</h6>
) : null}
</Wrapper>

<Wrapper padding={' py-[48px]'}>
{data ? (
<div className="flex flex-col sm:flex-row gap-[48px] mx-auto justify-center z-10 opacity-100 font-semibold">
<div className="flex flex-col gap-32p sm:mb-8">
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[0].title}
</div>
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[1].title}
</div>
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[2].title}
</div>
</div>
<div className="flex flex-col gap-32p sm:mt-8">
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[3].title}
</div>
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[4].title}
</div>
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[5].title}
</div>
</div>
<div className="flex flex-col gap-32p sm:mb-8">
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[6].title}
</div>
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[7].title}
</div>
<div className="bg-white py-32p px-[24px] rounded-[8px] text-center shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
{data.Spec[8].title}
</div>
</div>
</div>
</section>
</Wrapper>
<Wrapper padding={' py-[48px] mb-32p'}>
<h4 className='font-semibold font-secondary text-[#9B32CE] text-subtitle-48 text-center w-full'>How We Help Them?</h4>
</Wrapper>
<Wrapper padding={' py-90p'}>
<section>
<div className="flex flex-col justify-center items-start w-full max-w-custom m-auto px-8 xl:px-0 mb-32p">
<div className="flex flex-col gap-[72px] w-full max-w-[950px] mx-auto">
{_data.help.map((item, index) => (
<HelpParagraph
key={index}
title={item.title}
paragraph={item.paragraph}
/>
))}
) : null}
<div className="flex absolute w-full top-0 z-[-1]">
<div className="w-[624px] h-[624px] bg-indigo-500 opacity-25 rounded-full mx-auto blur-[100px]"></div>
</div>
</Wrapper>
</div>
{data ? (
<div className="md:mb-[200px]">
<div className="w-full relative mt-12 z-[-1]">
<div className="radial-gradient absolute top-0 left-0 right-0 bottom-0"></div>
<div className="max-w-custom mx-auto">
<img
src={api_url + data.OfficeImg.data.attributes.url}
alt={data.OfficeImgAlt}
></img>
</div>
</div>
<div className="max-w-[600px] mx-[16px] md:mx-auto md:mt-[-320px] p-[24px] flex flex-col gap-[24px] z-20 bg-white rounded-[16px] shadow-[0_3px_10px_rgb(0,0,0,0.2)] md:shadow-none">
<div className="flex flex-col gap-[8px]">
<h6 className="n-h3-heading text-dark-gray font-bold">
{data.Download.title}
</h6>
<p className="n-paragraph">{data.Download.paragraph}</p>
</div>
</section>
</Wrapper>
<Wrapper padding={' py-90p'} bg>
<h4 className='font-semibold font-secondary text-[#9B32CE] text-subtitle-48 text-center w-full py-32p'>What Our Customers Say?</h4>
<Testimonials noTitle />
</Wrapper>
<Wrapper padding={' py-[48px] mb-32p'}>
<h4 className='font-semibold font-secondary text-[#9B32CE] text-subtitle-48 text-center w-full py-32p'>Success</h4>
<p className='max-w-[1000px] mx-auto text-center w-full'>For us, the definition of success is a multifaceted subject. In short, we don’t declare a victory unless:</p>
<ul className='mx-[72px] lg:mx-[250px]'>
<li className='my-32p list-disc'>Deliverables are <b className='text-[#9B32CE]'>on time and within budget</b></li>
<li className='my-32p list-disc'>Deliverables are <b className='text-[#9B32CE]'>what the client needs</b>. We produce meaningful and positive contributions, we do not want to tick the checkboxes just so that we can call it done.</li>
<li className='my-32p list-disc'>Our resources involved with the client <b className='text-[#9B32CE]'>have gained knowledge in the process</b>, they understand the client’s business, what they’ve created and most importantly - why it was created</li>
<li className='my-32p list-disc'>Our clients can <b className='text-[#9B32CE]'>demonstratively measure the improvements</b> in stability, volume, earnings, their client/user satisfaction…as a result of our contribimport useAnalytics from './../hooks/useAnalytics';
utions. </li>

</ul>
</Wrapper>
<Wrapper padding={' py-32p'}>
<div className='flex flex-col md:flex gap-[32px] w-fit mx-auto'>
<CustomLink href={_data.downloadFilePath} downloadFile context={'Company Overview'}>
<p>Company Overview</p>
<DownalodIcon/>
</CustomLink>
</div>
</Wrapper>
<Wrapper padding={' py-90p'}>
<ActionCard
title="Let's Work Together!"
text="We’d be happy to try and find a way to contribute to your business."
btn2="Portfolio"
btn1="Contact Us"
link2={'/portfolio'}
link1={'/contact'}
/>
</Wrapper>
<CustomLink
href={download.downloadFilePath}
downloadFile={download.downloadFileName}
context={'Company Overview'}
>
<p>{data.Download.button}</p>
</CustomLink>
</div>
</div>
) : null}
{data ? (
<Wrapper padding={' py-90p'}>
<ActionCard
title={data.WorkTogether.title}
text={data.WorkTogether.paragraph}
btn2={data.WorkTogether.ButtonSecondary}
btn1={data.WorkTogether.ButtonPrimary}
link2={'/portfolio'}
link1={'/contact'}
/>
</Wrapper>
) : null}
</div>
)

}
</div>
</PageLayout>
);
}
};

export default WorkWithUs
export default WorkWithUs;

+ 2
- 2
frontend/src/styles/buttons.css Wyświetl plik

@@ -21,11 +21,11 @@
}

.btn-primary {
@apply px-64p py-20p text-center
@apply px-32p py-20p sm:px-64p text-center
text-btn uppercase font-semibold rounded-16 border-transparent cursor-pointer bg-gradient-to-r from-dg-secondary to-dg-primary-900 transition-all hover:bg-gradient-to-r hover:to-dg-secondary hover:from-dg-primary-900 hover:transition-all text-white;
}
.btn-secondary {
@apply px-64p py-20p text-center
@apply px-32p py-20p sm:px-64p text-center
text-btn uppercase font-semibold rounded-16 cursor-pointer border-2 border-dg-primary-400 transition-all hover:transition-all text-dg-primary-900;
}
.contact-us-link {

+ 17
- 1
frontend/src/styles/text.css Wyświetl plik

@@ -4,7 +4,7 @@

@layer components {
.heading {
@apply font-primary text-dark-gray dark:text-white text-head-mobile md:text-head;
@apply font-secondary font-bold text-dark-gray dark:text-white text-n-head-mobile md:text-n-head;
}

.subheading {
@@ -43,6 +43,22 @@
.title-italic {
@apply text-italic-title text-dg-primary-400 font-semibold italic my-8p capitalize;
}

.n-heading {
@apply font-secondary font-bold text-dark-gray dark:text-white text-n-head-mobile md:text-n-head;
}
.n-subheading{
@apply text-n-subhead-mobile md:text-n-subhead font-secondary uppercase text-dg-secondary font-semibold;
}
.n-h3-heading{
@apply text-n-h3-heading-mobile md:text-n-h3-heading font-secondary text-dg-primary-900 font-bold;
}
.n-paragraph {
@apply text-n-paragraph-mobile md:text-n-paragraph font-secondary text-dark-gray font-normal
}
.n-paragraph-title {
@apply text-n-paragraph-title-mobile md:text-n-paragraph-title font-secondary text-dark-gray font-semibold
}
}

.no-wrap {

+ 13
- 0
frontend/src/utils/strapiApiBuilder.js Wyświetl plik

@@ -0,0 +1,13 @@
const api_url = process.env.REACT_APP_API_URL;

export const strapiApiBuilder = (page, stringArray) => {
const api = `${api_url}/api/${page}`;
let query = '';
stringArray.map((field, index) => {
if (index === 0) query += `?populate[${index}]=${field}`;
else {
query += `&populate[${index}]=${field}`;
}
});
return api + query;
};

+ 95
- 25
frontend/tailwind.config.js Wyświetl plik

@@ -3,8 +3,8 @@ module.exports = {
darkMode: 'class',
theme: {
fontFamily: {
'primary' : ['"Abril Fatface"','serif'],
'secondary' : ['"Poppins"', 'sans-serif'],
primary: ['"Abril Fatface"', 'serif'],
secondary: ['"Poppins"', 'sans-serif'],
},
fontSize: {
'head' : ['56px', {
@@ -74,17 +74,83 @@ module.exports = {
'subtitle-48' : ['48px', {
letterSpacing: '0px',
lineHeight: 'normal'
}]
}],

//
'n-head' : ['54.00px', {
letterSpacing: '-0.6%',
lineHeight: '125%',
}],
'n-subhead' : ['16px', {
letterSpacing: '1.5px',
lineHeight: '24px',
}],
'n-head-mobile' : ['24px', {
letterSpacing: '-0.6%',
lineHeight: '32px',
}],
'n-subhead-mobile' : ['10.5px', {
letterSpacing: '1.5px',
lineHeight: '28px',
}],
'n-paragraph' : ['16px', {
letterSpacing: '0%',
lineHeight: '28px',
}],
'n-paragraph-mobile' : ['14px', {
letterSpacing: '0%',
lineHeight: '24px',
}],
'n-h3-heading' : ['24px', {
letterSpacing: '-0.6%',
lineHeight: '32px',
}],
'n-h3-heading-mobile' : ['18.66px', {
letterSpacing: '0%',
lineHeight: '24px',
}],
'n-paragraph-title-mobile' : ['14px', {
letterSpacing: '0%',
lineHeight: '24px',
}],
'n-paragraph-title' : ['18px', {
letterSpacing: '0%',
lineHeight: 'normal',
}],
'banner-mobile': [
'18.66px',
{
letterSpacing: '0px',
lineHeight: '24px',
},
],
'banner-p': [
'14px',
{
letterSpacing: '0px',
lineHeight: '21px',
},
],
'banner-p-mobile': [
'12px',
{
letterSpacing: '0px',
lineHeight: '18px',
},
],


},
minHeight: {
'12': '3rem',
12: '3rem',
},
maxWidth: {
'780p':'780px',
'wrapper': '1150px',
'custom': '1150px',
'dropzone': '110px',
'780p': '780px',
wrapper: '1150px',
custom: '1150px',
dropzone: '110px',
banner: '1118px',
banner_m: '309px',
},
transitionDuration: {
DEFAULT: '300ms',
@@ -97,6 +163,7 @@ module.exports = {
'baby-blue': '#f0f3f9',
'dg-primary': {
50: '#f4e9f4',
75: '#fafafa',
100: '#e9d4e9',
200: '#debedd',
300: '#d3a9d2',
@@ -121,29 +188,32 @@ module.exports = {
black: '#000000',
},
spacing: {
'2p': "2px",
'4p':'4px',
'2p': '2px',
'4p': '4px',
'8p': '8px',
'12p':'12px',
'12p': '12px',
'15p': '15px',
'16p': '16px',
'20p':'20px',
'32p':'32px',
'48p':'48px',
'64p':'64px',
'72p':'72px',
'90p':'90px',
'140p':'140px',
'20p': '20px',
'32p': '32px',
'42p': '42px',
'48p': '48px',
'64p': '64px',
'72p': '72px',
'90p': '90px',
'140p': '140px',
'164p': '164px',
'200p': '200px',
'240p':'240px'


'240p': '240px',
},
borderRadius: {
'8': '8px',
'16': '16px',
'32' : '32px'
}
8: '8px',
16: '16px',
32: '32px',
},
boxShadow: {
custom: '0 0px 9px 9px rgba(0, 0, 0, 0.09)',
},
},
},
plugins: [

+ 118
- 10
frontend/yarn.lock Wyświetl plik

@@ -1791,6 +1791,11 @@
dependencies:
"@types/node" "*"

"@types/cookie@^0.3.3":
"integrity" "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
"resolved" "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz"
"version" "0.3.3"

"@types/debug@^4.0.0":
"integrity" "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg=="
"resolved" "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz"
@@ -1862,6 +1867,14 @@
dependencies:
"@types/unist" "*"

"@types/hoist-non-react-statics@^3.0.1":
"integrity" "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA=="
"resolved" "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
"version" "3.3.1"
dependencies:
"@types/react" "*"
"hoist-non-react-statics" "^3.3.0"

"@types/html-minifier-terser@^6.0.0":
"integrity" "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg=="
"resolved" "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz"
@@ -1973,7 +1986,7 @@
"resolved" "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz"
"version" "1.2.4"

"@types/react@>=16":
"@types/react@*", "@types/react@>=16":
"integrity" "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA=="
"resolved" "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz"
"version" "18.0.21"
@@ -2643,6 +2656,14 @@
dependencies:
"follow-redirects" "^1.14.8"

"axios@^0.27.2":
"integrity" "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ=="
"resolved" "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz"
"version" "0.27.2"
dependencies:
"follow-redirects" "^1.14.9"
"form-data" "^4.0.0"

"axobject-query@^2.2.0":
"integrity" "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA=="
"resolved" "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz"
@@ -2835,6 +2856,11 @@
"resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
"version" "1.0.2"

"base-64@^1.0.0":
"integrity" "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
"resolved" "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz"
"version" "1.0.0"

"batch@0.6.1":
"integrity" "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY="
"resolved" "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz"
@@ -3297,7 +3323,7 @@
"resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz"
"version" "1.0.6"

"cookie@0.4.1":
"cookie@^0.4.0", "cookie@0.4.1":
"integrity" "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
"resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz"
"version" "0.4.1"
@@ -4645,10 +4671,10 @@
"resolved" "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz"
"version" "3.2.4"

"follow-redirects@^1.0.0", "follow-redirects@^1.14.8":
"integrity" "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA=="
"resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz"
"version" "1.14.8"
"follow-redirects@^1.0.0", "follow-redirects@^1.14.8", "follow-redirects@^1.14.9":
"integrity" "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
"resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz"
"version" "1.15.2"

"fork-ts-checker-webpack-plugin@^6.5.0":
"integrity" "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw=="
@@ -4678,6 +4704,15 @@
"combined-stream" "^1.0.8"
"mime-types" "^2.1.12"

"form-data@^4.0.0":
"integrity" "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww=="
"resolved" "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz"
"version" "4.0.0"
dependencies:
"asynckit" "^0.4.0"
"combined-stream" "^1.0.8"
"mime-types" "^2.1.12"

"formik@^2.2.9":
"integrity" "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA=="
"resolved" "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz"
@@ -5241,7 +5276,7 @@
"resolved" "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz"
"version" "2.2.0"

"invariant@2.2.4":
"invariant@^2.2.4", "invariant@2.2.4":
"integrity" "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="
"resolved" "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz"
"version" "2.2.4"
@@ -6292,6 +6327,15 @@
dependencies:
"sourcemap-codec" "^1.4.4"

"mailgun.js@^8.0.6":
"integrity" "sha512-b+c7QO1T4oFsudEcRB2H7oZKth8ZDeYRW4xjW12QQVNYDSJCVxqSQfps6ofcH8fqcCMJdzc76HVNGdnUZgBPCw=="
"resolved" "https://registry.npmjs.org/mailgun.js/-/mailgun.js-8.0.6.tgz"
"version" "8.0.6"
dependencies:
"axios" "^0.27.2"
"base-64" "^1.0.0"
"url-join" "^4.0.1"

"make-dir@^3.0.0", "make-dir@^3.0.2", "make-dir@^3.1.0":
"integrity" "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="
"resolved" "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz"
@@ -7726,7 +7770,7 @@
"kleur" "^3.0.3"
"sisteransi" "^1.0.5"

"prop-types@^15.0.0", "prop-types@^15.5.10", "prop-types@^15.7.2", "prop-types@^15.8.1":
"prop-types@^15.0.0", "prop-types@^15.5.0", "prop-types@^15.5.10", "prop-types@^15.6.0", "prop-types@^15.7.2", "prop-types@^15.8.1":
"integrity" "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="
"resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
"version" "15.8.1"
@@ -7824,6 +7868,23 @@
"regenerator-runtime" "^0.13.9"
"whatwg-fetch" "^3.6.2"

"react-async-script@^1.1.1":
"integrity" "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q=="
"resolved" "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz"
"version" "1.2.0"
dependencies:
"hoist-non-react-statics" "^3.3.0"
"prop-types" "^15.5.0"

"react-cookie@^4.1.1":
"integrity" "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A=="
"resolved" "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz"
"version" "4.1.1"
dependencies:
"@types/hoist-non-react-statics" "^3.0.1"
"hoist-non-react-statics" "^3.0.0"
"universal-cookie" "^4.0.0"

"react-dev-utils@^12.0.0":
"integrity" "sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ=="
"resolved" "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz"
@@ -7854,7 +7915,7 @@
"strip-ansi" "^6.0.1"
"text-table" "^0.2.0"

"react-dom@*", "react-dom@^16 || ^17 || ^18", "react-dom@^16.8 || ^17 || ^18", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.2", "react-dom@>= 16.8.0", "react-dom@>=16.8", "react-dom@>=16.8 || ^17.0.0 || ^18.0.0":
"react-dom@*", "react-dom@^16 || ^17 || ^18", "react-dom@^16.6.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8 || ^17 || ^18", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.2", "react-dom@>= 16.8.0", "react-dom@>=16.8", "react-dom@>=16.8 || ^17.0.0 || ^18.0.0":
"integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA=="
"resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz"
"version" "17.0.2"
@@ -7882,6 +7943,40 @@
"resolved" "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz"
"version" "2.0.4"

"react-fast-compare@^3.2.0":
"integrity" "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
"resolved" "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz"
"version" "3.2.0"

"react-ga@^3.3.1":
"integrity" "sha512-4Vc0W5EvXAXUN/wWyxvsAKDLLgtJ3oLmhYYssx+YzphJpejtOst6cbIHCIyF50Fdxuf5DDKqRYny24yJ2y7GFQ=="
"resolved" "https://registry.npmjs.org/react-ga/-/react-ga-3.3.1.tgz"
"version" "3.3.1"

"react-ga4@^1.4.1":
"integrity" "sha512-ioBMEIxd4ePw4YtaloTUgqhQGqz5ebDdC4slEpLgy2sLx1LuZBC9iYCwDymTXzcntw6K1dHX183ulP32nNdG7w=="
"resolved" "https://registry.npmjs.org/react-ga4/-/react-ga4-1.4.1.tgz"
"version" "1.4.1"

"react-google-recaptcha@^2.1.0":
"integrity" "sha512-K9jr7e0CWFigi8KxC3WPvNqZZ47df2RrMAta6KmRoE4RUi7Ys6NmNjytpXpg4HI/svmQJLKR+PncEPaNJ98DqQ=="
"resolved" "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-2.1.0.tgz"
"version" "2.1.0"
dependencies:
"prop-types" "^15.5.0"
"react-async-script" "^1.1.1"

"react-helmet-async@^1.3.0":
"integrity" "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg=="
"resolved" "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz"
"version" "1.3.0"
dependencies:
"@babel/runtime" "^7.12.5"
"invariant" "^2.2.4"
"prop-types" "^15.7.2"
"react-fast-compare" "^3.2.0"
"shallowequal" "^1.1.0"

"react-is@^16.13.1", "react-is@^16.7.0", "react-is@>= 16.8.0":
"integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
"resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
@@ -8001,7 +8096,7 @@
optionalDependencies:
"fsevents" "^2.3.2"

"react@*", "react@^16 || ^17 || ^18", "react@^16.8 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.2", "react@>= 16", "react@>= 16.8", "react@>= 16.8.0", "react@>=15", "react@>=16", "react@>=16.8", "react@>=16.8 || ^17.0.0 || ^18.0.0", "react@>=16.8.0", "react@17.0.2":
"react@*", "react@^15.6.2 || ^16.0 || ^17 || ^18", "react@^16 || ^17 || ^18", "react@^16.6.0 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.2", "react@>= 16", "react@>= 16.3.0", "react@>= 16.8", "react@>= 16.8.0", "react@>=15", "react@>=16", "react@>=16.4.1", "react@>=16.8", "react@>=16.8 || ^17.0.0 || ^18.0.0", "react@>=16.8.0", "react@17.0.2":
"integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="
"resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
"version" "17.0.2"
@@ -9338,6 +9433,14 @@
"unist-util-is" "^5.0.0"
"unist-util-visit-parents" "^5.0.0"

"universal-cookie@^4.0.0":
"integrity" "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw=="
"resolved" "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz"
"version" "4.0.4"
dependencies:
"@types/cookie" "^0.3.3"
"cookie" "^0.4.0"

"universalify@^0.1.2":
"integrity" "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
"resolved" "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz"
@@ -9370,6 +9473,11 @@
dependencies:
"punycode" "^2.1.0"

"url-join@^4.0.1":
"integrity" "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
"resolved" "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz"
"version" "4.0.1"

"util-deprecate@^1.0.1", "util-deprecate@^1.0.2", "util-deprecate@~1.0.1":
"integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
"resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"

Ładowanie…
Anuluj
Zapisz