Ver código fonte

updates to career page

blog-new
Pavle Golubovic 3 anos atrás
pai
commit
89dcb8d579

+ 97
- 0
frontend/package-lock.json Ver arquivo

@@ -24,6 +24,7 @@
"form-data": "^4.0.0",
"formik": "^2.2.9",
"framer-motion": "^6.3.4",
"gsap": "^3.11.4",
"mailgun.js": "^8.0.6",
"prop-types": "^15.8.1",
"react": "^17.0.2",
@@ -8504,6 +8505,11 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
},
"node_modules/gsap": {
"version": "3.11.4",
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.11.4.tgz",
"integrity": "sha512-McHhEguHyExMMnjqKA8G+7TvxmlKQGMbjgwAilnFe1e4id7V/tFveRQ2YMZhTYu0oxHGWvbPltdVYQOu3z1SCA=="
},
"node_modules/gzip-size": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
@@ -14621,6 +14627,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-intersection-observer": {
"version": "9.4.1",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz",
@@ -24143,6 +24196,11 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
},
"gsap": {
"version": "3.11.4",
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.11.4.tgz",
"integrity": "sha512-McHhEguHyExMMnjqKA8G+7TvxmlKQGMbjgwAilnFe1e4id7V/tFveRQ2YMZhTYu0oxHGWvbPltdVYQOu3z1SCA=="
},
"gzip-size": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
@@ -28379,6 +28437,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-intersection-observer": {
"version": "9.4.1",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz",

+ 1
- 0
frontend/package.json Ver arquivo

@@ -19,6 +19,7 @@
"form-data": "^4.0.0",
"formik": "^2.2.9",
"framer-motion": "^6.3.4",
"gsap": "^3.11.4",
"mailgun.js": "^8.0.6",
"prop-types": "^15.8.1",
"react": "^17.0.2",

+ 2
- 1
frontend/src/App.js Ver arquivo

@@ -29,6 +29,7 @@ const CaseStudyResource = lazy(() => import('./pages/CaseStudyResource'));
const CaseStudyStrata = lazy(() => import('./pages/CaseStudyStrata'));
const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy'));
const WorkWithUs = lazy(() => import('./pages/WorkWithUs'));
import NavigationNew from './components/shared/NavigationNew';

// Navigation Links
const links = routes.filter(item => item.nav === true);
@@ -51,7 +52,6 @@ function App() {
function scrollToView(event) {
event.preventDefault();
if (forwardedRef) {
//console.log(forwardedRef.current.offsetTop);
window.scrollTo({ behavior: 'smooth', top: forwardedRef.current.offsetTop });
} else {
link('/contact');
@@ -96,6 +96,7 @@ function App() {
<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="/diligentlife" element={<DiligentLife />}/>
<Route exact path="/diligentminds" element={<DiligentMinds />}/>
<Route exact path="/eventstimeline" element={<EventsTimeline />}/>

+ 3
- 0
frontend/src/assets/chevron.svg Ver arquivo

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="-4 -4 32 32" stroke-width="1.5" stroke="currentColor" class="w-3 h-3">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
</svg>

+ 0
- 1
frontend/src/components/BlogSection.jsx Ver arquivo

@@ -20,7 +20,6 @@ export default function BlogSection(props) {
axios
.get(`${api_url}/api/blogpage?populate[0]=post.image`)
.then(res => {
//console.log(res.data.data.attributes);
setCntBlog(res.data.data.attributes);
setIsLoaded(true);
})

+ 6
- 12
frontend/src/components/CareerCardsTemplates/ExpandedCard.jsx Ver arquivo

@@ -45,18 +45,12 @@ const _card = {
const ExpandedCard = ({ card, setExpanded, setExpandedCard }) => {
const linkTo = useNavigate();

const {uiContext, setUiContext} = useContext(UIContext);
const handleNavigate = (tab, position) => {
linkTo('/contact', { tab: { tab}, position: { position } });
}

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

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

return (
@@ -125,7 +119,7 @@ const ExpandedCard = ({ card, setExpanded, setExpandedCard }) => {
<a
href="/contact"
className="btn btn_primary mt-8 transition-all hover:transition-all"
onClick={()=> handleContext(card.id)}
onClick={handleNavigate(false, ".Net")}
>
Apply
</a>
@@ -194,7 +188,7 @@ const ExpandedCard = ({ card, setExpanded, setExpandedCard }) => {
<a
href="/contact"
className="btn btn_primary mt-8 transition-all hover:transition-all"
onClick={()=> handleContext(card.id)}
onClick={handleNavigate(false, ".Net")}
>
Apply
</a>

+ 93
- 0
frontend/src/components/HRProcess.jsx Ver arquivo

@@ -0,0 +1,93 @@
import React, {useRef, useEffect} from 'react';
import { useScroll } from 'framer-motion';
import { ref } from 'yup';

const HRProcess = ({cntCareers, img}) => {

const ref = useRef(null);
const { scrollYProgress } = useScroll({ container: ref });
// gsap.registerPlugin(ScrollTrigger);
useEffect(() => {
const removeB = scrollYProgress.onChange((value) => {
if (value > 0.5)
{
document.querySelector('#img-one').classList.add('opacity-0');
document.querySelector('#img-one').classList.remove('opacity-1');
document.querySelector('#img-two').classList.remove('opacity-0');
document.querySelector('#img-two').classList.add('opacity-1');
}
else{
document.querySelector('#img-one').classList.remove('opacity-0');
document.querySelector('#img-one').classList.add('opacity-1');
document.querySelector('#img-two').classList.add('opacity-0');
document.querySelector('#img-two').classList.remove('opacity-1');
}
}
);

return () => {
removeB();
};
});


return (
<div
ref={ref}
id="steps-container"
className="steps-container flex flex-col items-center justify-start overflow-auto h-[75vh] pt-72p pl-3"
>
{/* Dynamic Image */}

<img
id="img-one"
src={img}
alt="Image not found"
className="bg-fixed hidden sm:block absolute top-1/4 left-1/2 w-2/5 transition-all "
/>
<img
id="img-two"
src={img}
alt="Image not found"
className="bg-fixed hidden sm:block opacity-0 absolute top-1/4 left-1/2 w-2/5 transition-all rotate-180"
/>

<div className="local">
{cntCareers.selection_process.steps.map((item, index) => (
<>
{/* Section */}
<div
id={item.id}
className="relative flex flex-col sm:flex-row items-start justify-center sm:gap-16 min-h-fit max-h[100vh] mb-28 md:mb-56"
>
{/* Line */}
<hr className="bg-gray-400 w-full absolute -left-1/2 rotate-90" />

{/* Dot */}
<div className="z-10 p-[0.36rem] rounded-full bg-white border-solid border border-dg-primary-900 absolute -left-[0.63%] top-[1%]"></div>

<div className="sm:w-1/2 ml-8">
<h3 className="h3-heading">{item.heading}</h3>
<p className="text-sm text-dark-gray dark:text-white mt-4">
{item.paragraph}
</p>
{item.cto != null && (
<button className="btn-secondary mt-6 min-w-fit">
{item.cto}
</button>
)}
</div>
<div className="w-1/2"></div>
</div>
</>
))}
</div>
</div>
)
}

export default HRProcess

+ 0
- 4
frontend/src/components/PortfolioCard.jsx Ver arquivo

@@ -6,10 +6,6 @@ const api_url = process.env.REACT_APP_API_URL;
const PortfolioCard = ({ title, isLarge, link, img, alt }) => {
const linkTo = useNavigate();

useEffect(() => {
//console.log(isLarge);
});

return (
// <div className={"card box" + (isLarge ? ' col-span-2' : '')}>
<a className={'card box my-2 flex- flex-col items-center'} href={link}>

+ 0
- 1
frontend/src/components/ServicesHome.jsx Ver arquivo

@@ -40,7 +40,6 @@ export default function ServicesHome() {
`${api_url}/api/homepage?populate[0]=services&populate[1]=services.heading&populate[2]=services.serviceHome.icon`,
)
.then(res => {
//console.log(res.data.data.attributes);
setCntServicesHome(res.data.data.attributes);
setIsLoaded(true);
})

+ 9
- 3
frontend/src/components/shared/ClientForm.jsx Ver arquivo

@@ -10,11 +10,13 @@ import { motion } from 'framer-motion';
import ReactGA from 'react-ga4';
import ReCAPTCHA from 'react-google-recaptcha';
import axios from 'axios';
import { useEffect } from 'react';

const api_url = process.env.REACT_APP_API_URL;

export default function ClientForm({ mg, img }) {
export default function ClientForm({ mg, img, cta }) {
//search context for prevous entry TODO
const [btnText, setBtnText] = useState('');
const { clientForm, setClientForm } = useContext(ClientFormContext);
const [sucMsg, setSucMsg] = useState(false);
const captchaRef = useRef(null);
@@ -27,6 +29,10 @@ export default function ClientForm({ mg, img }) {
});
};

useEffect(() => {
setBtnText(cta);
},[cta]);




@@ -95,7 +101,7 @@ export default function ClientForm({ mg, img }) {
} else setMsgText('Please fill reCAPTCHA and try again. Thank you!');
})
.catch(error => {
console.log(error);
//console.log(error);
});
}
ReactGA.event('contact', {
@@ -239,7 +245,7 @@ export default function ClientForm({ mg, img }) {
type="submit"
className="btn btn_primary transition-all inline-flex justify-center py-4 px-14 border border-transparent shadow-md text-sm font-semibold rounded-xl text-white bg-dg-primary-600 hover:bg-dg-primary-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-dg-primary-600"
>
{props.cta}
{btnText}
</button>
</div>
{sucMsg && (

+ 7
- 7
frontend/src/components/shared/Contact.jsx Ver arquivo

@@ -26,8 +26,8 @@ const mg = mailgun.client({
url: 'https://api.eu.mailgun.net',
});

export default function Contact({job, business, defaultIndex}) {
const [tab, setTab] = useState(true);
export default function Contact({activeTab, position, job, business}) {
const [tab, setTab] = useState(activeTab);
const [tabTitle, setTabTitle] = useState(business.title);

function handleContextMenu(event) {
@@ -76,8 +76,6 @@ export default function Contact({job, business, defaultIndex}) {

const api_url = process.env.REACT_APP_API_URL;

let defaultPositionSelection = null;

const [clientForm, setClientForm] = useState(initialClientValues);
const [jobForm, setJobForm] = useState(initialJobValues);

@@ -91,7 +89,6 @@ export default function Contact({job, business, defaultIndex}) {
`${api_url}/api/careerspage?populate[0]=heading&populate[1]=info&populate[2]=job.icon`,
)
.then(res => {
//console.log(res.data.data.attributes);
setCntCareers(res.data.data.attributes);
setIsLoaded(true);
})
@@ -101,6 +98,10 @@ export default function Contact({job, business, defaultIndex}) {
});
}, []);

useEffect(() => {
console.log(position);
})

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">
@@ -120,7 +121,7 @@ export default function Contact({job, business, defaultIndex}) {
<div className="py-16 relative">
<div className="flex justify-end flex-col">
<Tab.Group
defaultIndex={defaultIndex}
defaultIndex={tab ? 0 : 1}
onChange={index => handleTab(index)}
>
<div
@@ -181,7 +182,6 @@ export default function Contact({job, business, defaultIndex}) {
cta={job.cta}
img={job.image}
cntCareers={cntCareers}
defaultPositionSelection={defaultPositionSelection}
mg={mg}
/>
</JobFormContext.Provider>

+ 3
- 2
frontend/src/components/shared/HashPositions.jsx Ver arquivo

@@ -12,8 +12,9 @@ const _data = {

export default function HashPositions(props) {
let defaultPositionSelection = props.defaultPositionSelection;
//let defaultPositionSelection = '#dotNet';
//const cntCareersJobs = props.cntCareers;
let [selected, setSelected] = useState('#dotNet');
let [selected, setSelected] = useState('');

function handleChange(event) {
setSelected(event.target.innerText);
@@ -42,7 +43,7 @@ export default function HashPositions(props) {
<span
onClick={() => {
props.setOtherInputState(true);
defaultPositionSelection = '';
defaultPositionSelection = '#dotNet';
handleChange(event);
props.hashToFormData(selected);
}}

+ 9
- 3
frontend/src/components/shared/JobForm.jsx Ver arquivo

@@ -16,6 +16,7 @@ import axios from 'axios';
const api_url = process.env.REACT_APP_API_URL;

export default function JobForm(props) {
const [btnText, setBtnText] = useState('');
const [sucMsg, setSucMsg] = useState(false);
const captchaRef = useRef(null);
const [msgText, setMsgText] = useState('');
@@ -53,6 +54,10 @@ export default function JobForm(props) {
});
}

useEffect(() => {
setBtnText(props.cta);
},[props.cta])

useEffect(() => {
if (jobForm.file !== '') {
setErrorMsg('');
@@ -191,7 +196,7 @@ export default function JobForm(props) {
name="position"
id="position"
onBlur={changeFormHandler}
value={selectedPosition.substring(1)}
value={selectedPosition.substring(1) || 0}
onChange={props.handleChange}
autoComplete="given-name"
className="mt-1 disabled:bg-gray-100 disabled:border-gray-300 focus:ring-dg-primary-600 focus:border-dg-primary-900 block w-full shadow-sm sm:text-sm border-dg-primary-600 rounded-md transition duration-200"
@@ -402,8 +407,9 @@ export default function JobForm(props) {
type="submit"
className="btn btn_primary transition-all inline-flex justify-center py-4 px-14 border border-transparent shadow-md text-sm font-semibold rounded-xl text-white bg-dg-primary-600 hover:bg-dg-primary-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-dg-primary-600"
>
{props.cta}
</button>
{btnText}
</button>
</div>
{sucMsg && (
<div className={'text-sm text-right text-dg-primary-900'}>

+ 110
- 27
frontend/src/components/shared/Navigation.jsx Ver arquivo

@@ -7,6 +7,10 @@ import { NavLink, useLocation, useNavigate } from 'react-router-dom';
import '../../App.css';
import Wrapper from '../../layout/Wrapper';
import menuIcon from './../../assets/icons/menu.svg';
import chevron from './../../assets/chevron.svg';
import { useState } from 'react';
import useHoverOtuside from '../../hooks/useHoverOutside';
import { ref } from 'yup';

export default function Navigation({ links, scrollToView, activeLinks, forwardedRef }) {
const location = useLocation();
@@ -15,7 +19,11 @@ export default function Navigation({ links, scrollToView, activeLinks, forwarded
home('/');
}

const { ref, show, setShow } = useHoverOtuside(false);

function showDrop() {
setShow(!show);
}

// Check if you are on HomePage to scroll to Contact us, or open a sepperate Contact us Page
function checkUrl(event) {
@@ -49,22 +57,68 @@ export default function Navigation({ links, scrollToView, activeLinks, forwarded
as="nav"
className="hidden md:flex space-x-8 lg:space-x-10 items-center"
>
{links.map((item,index) => (
<NavLink
key={index}
to={item.path}
className={({ isActive }) => {
return `text-p font-medium dark:text-white hover:text-dg-primary-900 focus:text-dg-primary-900 active:text-dg-primary-900 capitalize ${activeLinks(
isActive,
)}`;
}}
>
{item.title}
</NavLink>
))}
{links.map((item, index) =>
item.drop ? (
<div>
<a
href={item.path}
onMouseOver={() => showDrop()}
id="dropdownNavbarLink"
className="flex items-center justify-between w-full py-2 pl-3 pr-4 font-medium rounded text-gray-500 hover:text-dg-primary-900 focus:text-dg-primary-900 active:text-dg-primary-900 md:dark:hover:bg-transparent"
>
Careers
<svg
className="w-5 h-5 ml-1"
aria-hidden="true"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
></path>
</svg>
</a>
<div
ref={ref}
id="dropdownNavbar"
className={
(show ? 'absolute ' : 'hidden ') +
'z-10 font-normal bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700 dark:divide-gray-600'
}
>
<ul className="py-8 px-8 text-sm text-gray-500 dark:text-gray-400">
{item.drop.map((item2, index2) => (
<li key={index2}>
<a
href={item2.path}
className="text-p font-medium text-gray-500 dark:text-white hover:text-dg-primary-900 focus:text-dg-primary-900 active:text-dg-primary-900 capitalize whitespace-nowrap"
>
{item2.title}
</a>
</li>
))}
</ul>
</div>
</div>
) : (
<NavLink
key={index}
to={item.path}
className={({ isActive }) => {
return `text-p font-medium dark:text-white hover:text-dg-primary-900 focus:text-dg-primary-900 active:text-dg-primary-900 capitalize ${activeLinks(
isActive,
)}`;
}}
>
{item.title}
</NavLink>
),
)}
{/* React Router Link does not support Anchor tags */}
<div
// onClick={event => scrollToView(event)}
onClick={event => checkUrl(event)}
href="#contact"
className="contact-us-link text-p"
@@ -118,19 +172,48 @@ export default function Navigation({ links, scrollToView, activeLinks, forwarded
</div>
<div className="mt-6">
<nav className="grid gap-y-8">
{links.map((item,index) => (
<NavLink
onClick={() => close()}
key={index}
to={item.path}
className="text-p p-3 flex justify-center items-center rounded-md transition-all hover:transition-all hover:bg-dg-primary-900 hover:text-white"
>
<div aria-hidden="true" />
<span className="ml-3 text-base font-medium text-inherit">
{item.title}
</span>
</NavLink>
))}
{links.map((item, index) =>
item.drop ? (
<>
<NavLink
onClick={() => close()}
key={index}
to={item.path}
className="text-p p-3 flex justify-center items-center rounded-md transition-all hover:transition-all hover:bg-dg-primary-900 hover:text-white"
>
<div aria-hidden="true" />
<span className="ml-3 text-base font-medium text-inherit">
{item.title}
</span>
</NavLink>
{item.drop.map((item2, index2) => (
<NavLink
onClick={() => close()}
key={index2}
to={item2.path}
className="text-p p-3 flex justify-center items-center rounded-md transition-all hover:transition-all hover:bg-dg-primary-900 hover:text-white"
>
<div aria-hidden="true" />
<span className="ml-3 text-base font-medium text-inherit">
{item2.title}
</span>
</NavLink>
))}
</>
) : (
<NavLink
onClick={() => close()}
key={index}
to={item.path}
className="text-p p-3 flex justify-center items-center rounded-md transition-all hover:transition-all hover:bg-dg-primary-900 hover:text-white"
>
<div aria-hidden="true" />
<span className="ml-3 text-base font-medium text-inherit">
{item.title}
</span>
</NavLink>
),
)}
<a
href="#contact"
onClick={event => {

+ 179
- 0
frontend/src/components/shared/NavigationNew.jsx Ver arquivo

@@ -0,0 +1,179 @@
import { Fragment } from 'react';
import { Popover, Transition } from '@headlessui/react';
import PropTypes from 'prop-types';

import logo from '../../assets/logos/LogoFull.svg';
import { NavLink, useLocation, useNavigate } from 'react-router-dom';
import '../../App.css';
import Wrapper from '../../layout/Wrapper';
import menuIcon from './../../assets/icons/menu.svg';
import { useState } from 'react';

export default function NavigationNew({
links,
scrollToView,
activeLinks,
forwardedRef,
}) {
const [drop, setDrop] = useState(false);
const location = useLocation();
const home = useNavigate();
function handleLogo() {
home('/');
}

function showDrop() {
setDrop(!drop);
}

// Check if you are on HomePage to scroll to Contact us, or open a sepperate Contact us Page
function checkUrl(event) {
if (location.pathname === '/') scrollToView(event);
else home('/contact');
}

return (
<>
<nav className="bg-white dark:bg-dg-primary-1700 fixed w-full top-0 z-50">
<div className="container flex flex-wrap items-center justify-between mx-auto">
<a href="/" className="flex items-center">
<img src={logo} className="h-6 mr-3 sm:h-10" alt="Diligent Logo" />
</a>
<button
data-collapse-toggle="navbar-dropdown"
type="button"
className="inline-flex items-center p-2 ml-3 text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
aria-controls="navbar-dropdown"
aria-expanded="false"
>
<span className="sr-only">Open main menu</span>
<svg
className="w-6 h-6"
aria-hidden="true"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
clipRule="evenodd"
></path>
</svg>
</button>
<div className="hidden w-full md:block md:w-auto" id="navbar-dropdown">
<ul className="flex flex-col p-4 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 md:mt-0 md:text-sm md:font-medium md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700">
<li>
<a
href="#"
className="block py-2 pl-3 pr-4 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-white dark:bg-blue-600 md:dark:bg-transparent"
aria-current="page"
>
Home
</a>
</li>
<li>
<button
onClick={() => showDrop()}
id="dropdownNavbarLink"
className="flex items-center justify-between w-full py-2 pl-3 pr-4 font-medium text-gray-700 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 md:w-auto dark:text-gray-400 dark:hover:text-white dark:focus:text-white dark:border-gray-700 dark:hover:bg-gray-700 md:dark:hover:bg-transparent"
>
Dropdown{' '}
<svg
className="w-5 h-5 ml-1"
aria-hidden="true"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
></path>
</svg>
</button>
{/* <!-- Dropdown menu --> */}
<div
id="dropdownNavbar"
className={
(drop ? 'block ' : 'hidden ') +
'z-10 font-normal bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700 dark:divide-gray-600'
}
>
<ul
className="py-2 text-sm text-gray-700 dark:text-gray-400"
aria-labelledby="dropdownLargeButton"
>
<li>
<a
href="#"
className="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white"
>
Dashboard
</a>
</li>
<li>
<a
href="#"
className="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white"
>
Settings
</a>
</li>
<li>
<a
href="#"
className="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white"
>
Earnings
</a>
</li>
</ul>
<div className="py-1">
<a
href="#"
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-400 dark:hover:text-white"
>
Sign out
</a>
</div>
</div>
</li>
<li>
<a
href="#"
className="block py-2 pl-3 pr-4 text-gray-700 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-gray-400 md:dark:hover:text-white dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent"
>
Services
</a>
</li>
<li>
<a
href="#"
className="block py-2 pl-3 pr-4 text-gray-700 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-gray-400 md:dark:hover:text-white dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent"
>
Pricing
</a>
</li>
<li>
<a
href="#"
className="block py-2 pl-3 pr-4 text-gray-700 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 dark:text-gray-400 md:dark:hover:text-white dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent"
>
Contact
</a>
</li>
</ul>
</div>
</div>
</nav>
</>
);
}

NavigationNew.propTypes = {
links: PropTypes.arrayOf(PropTypes.object),
scrollToView: PropTypes.func,
activeLinks: PropTypes.func,
};

+ 1
- 1
frontend/src/context/index.js Ver arquivo

@@ -24,4 +24,4 @@ export const UIContext = React.createContext({
tab: true,
contactRef: '',
position: 0,
})
});

+ 21
- 0
frontend/src/hooks/useHoverOutside.js Ver arquivo

@@ -0,0 +1,21 @@
import { useState, useEffect, useRef } from 'react';

export default function useHoverOutside(initialIsVisible) {
const [show, setShow] = useState(initialIsVisible);
const ref = useRef(null);

const handleHoverOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setShow(false);
}
};

useEffect(() => {
document.addEventListener('mouseover', handleHoverOutside, true);
return () => {
document.removeEventListener('mouseover', handleHoverOutside, true);
};
}, []);

return { ref, show, setShow };
}

+ 5
- 1
frontend/src/index.js Ver arquivo

@@ -6,6 +6,7 @@ import reportWebVitals from './reportWebVitals';
import { CookiesProvider } from 'react-cookie';
import { BrowserRouter } from 'react-router-dom';
import { HelmetProvider } from 'react-helmet-async';
import { UIContext } from './context/index';

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

@@ -14,7 +15,10 @@ ReactDOM.render(
<BrowserRouter>
<CookiesProvider>
<HelmetProvider>
<App />
<UIContext.Provider value={UIContext} >
<App />
</UIContext.Provider>
</HelmetProvider>
</CookiesProvider>
</BrowserRouter>

+ 4
- 45
frontend/src/pages/Careers.jsx Ver arquivo

@@ -1,4 +1,4 @@
import { useState, useEffect, useRef } from 'react';
import { useState, useEffect, useRef, useLayoutEffect } from 'react';
import axios from 'axios';

import ImgStep1 from '../assets/images/CaseStudy/CentralizedSmall.png';
@@ -30,6 +30,7 @@ import TimelineCard from '../components/TimelineCard';

import { useNavigate } from 'react-router-dom';
import useAnalytics from './../hooks/useAnalytics';
import HRProcess from '../components/HRProcess';

const api_url = process.env.REACT_APP_API_URL;

@@ -261,9 +262,7 @@ export default function Careers({ forwardedRef }) {
const [cntCareers, setCntCareers] = useState('');
const [isLoaded, setIsLoaded] = useState('');

{/*const { ref: myRef, inView: elementIsVisible } = useInView();*/}



useEffect(() => {
document.title = 'Careers';
@@ -351,47 +350,7 @@ export default function Careers({ forwardedRef }) {
heading={cntCareers.selection_process.heading.heading}
subheading={cntCareers.selection_process.heading.subheading}
/>
<div
id="steps-container"
className="no-scroll flex flex-col items-center justify-start overflow-auto h-[75vh] pt-72p pl-3"
>
{/* Dynamic Image */}
<img
id="steps-image"
src={ImgStep1}
alt="Image not found"
className="hidden sm:block absolute top-1/4 left-1/2 w-2/5 bg-fixed transition-all"
/>

{cntCareers.selection_process.steps.map((item, index) => (
<>
{/* Section */}
<div
id={item.id}
className="relative flex flex-col sm:flex-row items-start justify-center sm:gap-16 min-h-fit max-h[100vh] mb-28 md:mb-56"
>
{/* Line */}
<hr className="bg-gray-400 w-full absolute -left-1/2 rotate-90" />

{/* Dot */}
<div className="z-10 p-[0.36rem] rounded-full bg-white border-solid border border-dg-primary-900 absolute -left-[0.63%] top-[1%]"></div>

<div className="sm:w-1/2 ml-8">
<h3 className="h3-heading">{item.heading}</h3>
<p
className="text-sm text-dark-gray dark:text-white mt-4"
>
{item.paragraph}
</p>
{item.cto != null && (
<button className="btn-secondary mt-6 min-w-fit">{item.cto}</button>
)}
</div>
<div className="w-1/2"></div>
</div>
</>
))}
</div>
<HRProcess cntCareers={cntCareers} img={ImgStep1} />
</Wrapper>

{/* Open Positions */}

+ 40
- 8
frontend/src/pages/ContactPage.jsx Ver arquivo

@@ -1,12 +1,39 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useContext } from 'react';
import Contact from '../components/shared/Contact';
import { UIContext } from '../context';
import PageLayout from '../layout/PageLayout';
import useAnalytics from '../hooks/useAnalytics';
import useDataApi from './../hooks/useDataApi';
import ReactHelmet from './../components/shared/ReactHelmet';

function ContactPage() {
const [data, setData] = useState('');
const [isLoaded, setIsLoaded] = useState('');
const api_url = process.env.REACT_APP_API_URL;

const strapiPopulate = [
'BusinessInquiry',
'BusinessInquiry.image',
'ApplyPosition',
'ApplyPosition.image',
'SEO',
'SEO.metaSocial',
'SEO.metaImage',
'SEO.metaSocial.image',
];

const stringBuilder = () => {
let stringQuery = '';
strapiPopulate.map((item, index) => {
if (index !== 0) stringQuery += '&';
stringQuery += `populate=${item}`;
});
return stringQuery;
};

function ContactPage({tab, position}) {


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

useEffect(() => {
document.title = 'Contact Us';
@@ -16,11 +43,16 @@ function ContactPage() {

return (
<PageLayout>
{/* {data.SEO ? <ReactHelmet seo={data.SEO} /> : null} */}
<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>
<UIContext.Provider value={UIContext}>
<Contact />
</UIContext.Provider>
{data ?
<Contact
defaultIndex={tab}
position={position || ''}
job={data.ApplyPosition}
business={data.BusinessInquiry}
/> : null
}
</section>
</PageLayout>
);

+ 14
- 21
frontend/src/pages/Home.jsx Ver arquivo

@@ -32,6 +32,7 @@ import MapDilig from '../components/Map';
import useDataApi from '../hooks/useDataApi';
import useAnalytics from '../hooks/useAnalytics';
import ReactHelmet from '../components/shared/ReactHelmet';
import { UIContext } from './../context/index';

const api_url = process.env.REACT_APP_API_URL;

@@ -55,15 +56,15 @@ const strapiPopulate = [
'ProcessMobileImg',
'ProcessMobileImg.Image',
'CaseStudies',
'BusinessInquiry',
'BusinessInquiry.image',
'ApplyPosition',
'ApplyPosition.image',
'Map',
'SEO',
'SEO.metaSocial',
'SEO.metaImage',
'SEO.metaSocial.image',
'BusinessInquiry',
'BusinessInquiry.image',
'ApplyPosition',
'ApplyPosition.image',
];

const stringBuilder = () => {
@@ -108,20 +109,8 @@ export default function Home({ forwardedRef }) {
} else {
return (
<PageLayout>
{cnt.SEO && <ReactHelmet seo={cnt.SEO} />}
{/* {(data && data.SEO !== undefined) ? <ReactHelmet seo={data.SEO} /> : null} */}
<div className="bg-white dark:bg-dg-primary-1700 w-full pt-32 overflow-hidden">
{/* <FormSwitch /> */}

{/* <Tab.Group>
<Tab.List>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
</Tab.List>
<Tab.Panels>
<Tab.Panel><ClientForm /></Tab.Panel>
<Tab.Panel><JobForm /></Tab.Panel>
</Tab.Panels>
</Tab.Group> */}

{/* Landing Section */}
{data ? (
@@ -174,14 +163,18 @@ export default function Home({ forwardedRef }) {
/>
) : null}




{/* Contact Section */}
{data ? (
<section id="contact" className="" ref={forwardedRef}>
<Contact
defaultIndex={0}
job={data.ApplyPosition}
business={data.BusinessInquiry}
/>
defaultIndex={true}
position={''}
job={data.ApplyPosition}
business={data.BusinessInquiry}
/>
</section>
) : null}


+ 26
- 1
frontend/src/routes.js Ver arquivo

@@ -13,7 +13,9 @@ import Portfolio from "./pages/Portfolio";
import PrivacyPolicy from "./pages/PrivacyPolicy";
import ProcessPage from "./pages/ProcessPage";
import WorkWithUs from "./pages/WorkWithUs";

import EventsTimeline from "./pages/EventsTimeline";
import DiligentLife from "./pages/DiligentLife";
import DiligentMinds from "./pages/DiligentMinds";
const routes = [
{
path: '/',
@@ -84,6 +86,29 @@ const routes = [
title: 'Careers',
exact: true,
nav:true,
drop: [
{
path:"/diligentlife",
component: <DiligentLife />,
title: 'Diligent Life',
exact: true,
nav:true,
},
{
path:"/diligentminds",
component: <DiligentMinds />,
title: 'Diligent Minds',
exact: true,
nav:true,
},
{
path:"/eventstimeline",
component: <EventsTimeline />,
title: 'Events Timeline',
exact: true,
nav:true,
},
]
},
{
path: '/about',

+ 11
- 1
frontend/yarn.lock Ver arquivo

@@ -4943,6 +4943,11 @@
"resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz"
"version" "4.2.9"

"gsap@^3.11.4":
"integrity" "sha512-McHhEguHyExMMnjqKA8G+7TvxmlKQGMbjgwAilnFe1e4id7V/tFveRQ2YMZhTYu0oxHGWvbPltdVYQOu3z1SCA=="
"resolved" "https://registry.npmjs.org/gsap/-/gsap-3.11.4.tgz"
"version" "3.11.4"

"gzip-size@^6.0.0":
"integrity" "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q=="
"resolved" "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz"
@@ -7977,6 +7982,11 @@
"react-fast-compare" "^3.2.0"
"shallowequal" "^1.1.0"

"react-intersection-observer@^9.4.1":
"integrity" "sha512-IXpIsPe6BleFOEHKzKh5UjwRUaz/JYS0lT/HPsupWEQou2hDqjhLMStc5zyE3eQVT4Fk3FufM8Fw33qW1uyeiw=="
"resolved" "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz"
"version" "9.4.1"

"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"
@@ -8096,7 +8106,7 @@
optionalDependencies:
"fsevents" "^2.3.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":
"react@*", "react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "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"

Carregando…
Cancelar
Salvar