Selaa lähdekoodia

updates to career page

blog-new
Pavle Golubovic 3 vuotta sitten
vanhempi
commit
89dcb8d579

+ 97
- 0
frontend/package-lock.json Näytä tiedosto

"form-data": "^4.0.0", "form-data": "^4.0.0",
"formik": "^2.2.9", "formik": "^2.2.9",
"framer-motion": "^6.3.4", "framer-motion": "^6.3.4",
"gsap": "^3.11.4",
"mailgun.js": "^8.0.6", "mailgun.js": "^8.0.6",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react": "^17.0.2", "react": "^17.0.2",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" "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": { "node_modules/gzip-size": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" "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": { "node_modules/react-intersection-observer": {
"version": "9.4.1", "version": "9.4.1",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" "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": { "gzip-size": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" "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": { "react-intersection-observer": {
"version": "9.4.1", "version": "9.4.1",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz",

+ 1
- 0
frontend/package.json Näytä tiedosto

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

+ 2
- 1
frontend/src/App.js Näytä tiedosto

const CaseStudyStrata = lazy(() => import('./pages/CaseStudyStrata')); const CaseStudyStrata = lazy(() => import('./pages/CaseStudyStrata'));
const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy')); const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy'));
const WorkWithUs = lazy(() => import('./pages/WorkWithUs')); const WorkWithUs = lazy(() => import('./pages/WorkWithUs'));
import NavigationNew from './components/shared/NavigationNew';


// Navigation Links // Navigation Links
const links = routes.filter(item => item.nav === true); const links = routes.filter(item => item.nav === true);
function scrollToView(event) { function scrollToView(event) {
event.preventDefault(); event.preventDefault();
if (forwardedRef) { if (forwardedRef) {
//console.log(forwardedRef.current.offsetTop);
window.scrollTo({ behavior: 'smooth', top: forwardedRef.current.offsetTop }); window.scrollTo({ behavior: 'smooth', top: forwardedRef.current.offsetTop });
} else { } else {
link('/contact'); link('/contact');
<Route exact path="/workwithus" element={<WorkWithUs />} /> <Route exact path="/workwithus" element={<WorkWithUs />} />
<Route exact path="/portfolio" element={<Portfolio />} /> <Route exact path="/portfolio" element={<Portfolio />} />
<Route exact path="/process" element={<ProcessPage />} /> <Route exact path="/process" element={<ProcessPage />} />
<Route exact path="/careers" element={<Careers />}/>
<Route exact path="/diligentlife" element={<DiligentLife />}/> <Route exact path="/diligentlife" element={<DiligentLife />}/>
<Route exact path="/diligentminds" element={<DiligentMinds />}/> <Route exact path="/diligentminds" element={<DiligentMinds />}/>
<Route exact path="/eventstimeline" element={<EventsTimeline />}/> <Route exact path="/eventstimeline" element={<EventsTimeline />}/>

+ 3
- 0
frontend/src/assets/chevron.svg Näytä tiedosto

<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 Näytä tiedosto

axios axios
.get(`${api_url}/api/blogpage?populate[0]=post.image`) .get(`${api_url}/api/blogpage?populate[0]=post.image`)
.then(res => { .then(res => {
//console.log(res.data.data.attributes);
setCntBlog(res.data.data.attributes); setCntBlog(res.data.data.attributes);
setIsLoaded(true); setIsLoaded(true);
}) })

+ 6
- 12
frontend/src/components/CareerCardsTemplates/ExpandedCard.jsx Näytä tiedosto

const ExpandedCard = ({ card, setExpanded, setExpandedCard }) => { const ExpandedCard = ({ card, setExpanded, setExpandedCard }) => {
const linkTo = useNavigate(); 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 ( return (
<a <a
href="/contact" href="/contact"
className="btn btn_primary mt-8 transition-all hover:transition-all" className="btn btn_primary mt-8 transition-all hover:transition-all"
onClick={()=> handleContext(card.id)}
onClick={handleNavigate(false, ".Net")}
> >
Apply Apply
</a> </a>
<a <a
href="/contact" href="/contact"
className="btn btn_primary mt-8 transition-all hover:transition-all" className="btn btn_primary mt-8 transition-all hover:transition-all"
onClick={()=> handleContext(card.id)}
onClick={handleNavigate(false, ".Net")}
> >
Apply Apply
</a> </a>

+ 93
- 0
frontend/src/components/HRProcess.jsx Näytä tiedosto

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 Näytä tiedosto

const PortfolioCard = ({ title, isLarge, link, img, alt }) => { const PortfolioCard = ({ title, isLarge, link, img, alt }) => {
const linkTo = useNavigate(); const linkTo = useNavigate();


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

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

+ 0
- 1
frontend/src/components/ServicesHome.jsx Näytä tiedosto

`${api_url}/api/homepage?populate[0]=services&populate[1]=services.heading&populate[2]=services.serviceHome.icon`, `${api_url}/api/homepage?populate[0]=services&populate[1]=services.heading&populate[2]=services.serviceHome.icon`,
) )
.then(res => { .then(res => {
//console.log(res.data.data.attributes);
setCntServicesHome(res.data.data.attributes); setCntServicesHome(res.data.data.attributes);
setIsLoaded(true); setIsLoaded(true);
}) })

+ 9
- 3
frontend/src/components/shared/ClientForm.jsx Näytä tiedosto

import ReactGA from 'react-ga4'; import ReactGA from 'react-ga4';
import ReCAPTCHA from 'react-google-recaptcha'; import ReCAPTCHA from 'react-google-recaptcha';
import axios from 'axios'; import axios from 'axios';
import { useEffect } from 'react';


const api_url = process.env.REACT_APP_API_URL; 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 //search context for prevous entry TODO
const [btnText, setBtnText] = useState('');
const { clientForm, setClientForm } = useContext(ClientFormContext); const { clientForm, setClientForm } = useContext(ClientFormContext);
const [sucMsg, setSucMsg] = useState(false); const [sucMsg, setSucMsg] = useState(false);
const captchaRef = useRef(null); const captchaRef = useRef(null);
}); });
}; };


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







} else setMsgText('Please fill reCAPTCHA and try again. Thank you!'); } else setMsgText('Please fill reCAPTCHA and try again. Thank you!');
}) })
.catch(error => { .catch(error => {
console.log(error);
//console.log(error);
}); });
} }
ReactGA.event('contact', { ReactGA.event('contact', {
type="submit" 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" 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> </button>
</div> </div>
{sucMsg && ( {sucMsg && (

+ 7
- 7
frontend/src/components/shared/Contact.jsx Näytä tiedosto

url: 'https://api.eu.mailgun.net', 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); const [tabTitle, setTabTitle] = useState(business.title);


function handleContextMenu(event) { function handleContextMenu(event) {


const api_url = process.env.REACT_APP_API_URL; const api_url = process.env.REACT_APP_API_URL;


let defaultPositionSelection = null;

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


`${api_url}/api/careerspage?populate[0]=heading&populate[1]=info&populate[2]=job.icon`, `${api_url}/api/careerspage?populate[0]=heading&populate[1]=info&populate[2]=job.icon`,
) )
.then(res => { .then(res => {
//console.log(res.data.data.attributes);
setCntCareers(res.data.data.attributes); setCntCareers(res.data.data.attributes);
setIsLoaded(true); setIsLoaded(true);
}) })
}); });
}, []); }, []);


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

if (!isLoaded) { if (!isLoaded) {
return ( 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"> <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">
<div className="py-16 relative"> <div className="py-16 relative">
<div className="flex justify-end flex-col"> <div className="flex justify-end flex-col">
<Tab.Group <Tab.Group
defaultIndex={defaultIndex}
defaultIndex={tab ? 0 : 1}
onChange={index => handleTab(index)} onChange={index => handleTab(index)}
> >
<div <div
cta={job.cta} cta={job.cta}
img={job.image} img={job.image}
cntCareers={cntCareers} cntCareers={cntCareers}
defaultPositionSelection={defaultPositionSelection}
mg={mg} mg={mg}
/> />
</JobFormContext.Provider> </JobFormContext.Provider>

+ 3
- 2
frontend/src/components/shared/HashPositions.jsx Näytä tiedosto



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


function handleChange(event) { function handleChange(event) {
setSelected(event.target.innerText); setSelected(event.target.innerText);
<span <span
onClick={() => { onClick={() => {
props.setOtherInputState(true); props.setOtherInputState(true);
defaultPositionSelection = '';
defaultPositionSelection = '#dotNet';
handleChange(event); handleChange(event);
props.hashToFormData(selected); props.hashToFormData(selected);
}} }}

+ 9
- 3
frontend/src/components/shared/JobForm.jsx Näytä tiedosto

const api_url = process.env.REACT_APP_API_URL; const api_url = process.env.REACT_APP_API_URL;


export default function JobForm(props) { export default function JobForm(props) {
const [btnText, setBtnText] = useState('');
const [sucMsg, setSucMsg] = useState(false); const [sucMsg, setSucMsg] = useState(false);
const captchaRef = useRef(null); const captchaRef = useRef(null);
const [msgText, setMsgText] = useState(''); const [msgText, setMsgText] = useState('');
}); });
} }


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

useEffect(() => { useEffect(() => {
if (jobForm.file !== '') { if (jobForm.file !== '') {
setErrorMsg(''); setErrorMsg('');
name="position" name="position"
id="position" id="position"
onBlur={changeFormHandler} onBlur={changeFormHandler}
value={selectedPosition.substring(1)}
value={selectedPosition.substring(1) || 0}
onChange={props.handleChange} onChange={props.handleChange}
autoComplete="given-name" 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" 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"
type="submit" 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" 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> </div>
{sucMsg && ( {sucMsg && (
<div className={'text-sm text-right text-dg-primary-900'}> <div className={'text-sm text-right text-dg-primary-900'}>

+ 110
- 27
frontend/src/components/shared/Navigation.jsx Näytä tiedosto

import '../../App.css'; import '../../App.css';
import Wrapper from '../../layout/Wrapper'; import Wrapper from '../../layout/Wrapper';
import menuIcon from './../../assets/icons/menu.svg'; 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 }) { export default function Navigation({ links, scrollToView, activeLinks, forwardedRef }) {
const location = useLocation(); const location = useLocation();
home('/'); 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 // Check if you are on HomePage to scroll to Contact us, or open a sepperate Contact us Page
function checkUrl(event) { function checkUrl(event) {
as="nav" as="nav"
className="hidden md:flex space-x-8 lg:space-x-10 items-center" 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 */} {/* React Router Link does not support Anchor tags */}
<div <div
// onClick={event => scrollToView(event)}
onClick={event => checkUrl(event)} onClick={event => checkUrl(event)}
href="#contact" href="#contact"
className="contact-us-link text-p" className="contact-us-link text-p"
</div> </div>
<div className="mt-6"> <div className="mt-6">
<nav className="grid gap-y-8"> <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 <a
href="#contact" href="#contact"
onClick={event => { onClick={event => {

+ 179
- 0
frontend/src/components/shared/NavigationNew.jsx Näytä tiedosto

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 Näytä tiedosto

tab: true, tab: true,
contactRef: '', contactRef: '',
position: 0, position: 0,
})
});

+ 21
- 0
frontend/src/hooks/useHoverOutside.js Näytä tiedosto

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 Näytä tiedosto

import { CookiesProvider } from 'react-cookie'; import { CookiesProvider } from 'react-cookie';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import { HelmetProvider } from 'react-helmet-async'; import { HelmetProvider } from 'react-helmet-async';
import { UIContext } from './context/index';


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


<BrowserRouter> <BrowserRouter>
<CookiesProvider> <CookiesProvider>
<HelmetProvider> <HelmetProvider>
<App />
<UIContext.Provider value={UIContext} >
<App />
</UIContext.Provider>
</HelmetProvider> </HelmetProvider>
</CookiesProvider> </CookiesProvider>
</BrowserRouter> </BrowserRouter>

+ 4
- 45
frontend/src/pages/Careers.jsx Näytä tiedosto

import { useState, useEffect, useRef } from 'react';
import { useState, useEffect, useRef, useLayoutEffect } from 'react';
import axios from 'axios'; import axios from 'axios';


import ImgStep1 from '../assets/images/CaseStudy/CentralizedSmall.png'; import ImgStep1 from '../assets/images/CaseStudy/CentralizedSmall.png';


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


const api_url = process.env.REACT_APP_API_URL; const api_url = process.env.REACT_APP_API_URL;


const [cntCareers, setCntCareers] = useState(''); const [cntCareers, setCntCareers] = useState('');
const [isLoaded, setIsLoaded] = useState(''); const [isLoaded, setIsLoaded] = useState('');


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




useEffect(() => { useEffect(() => {
document.title = 'Careers'; document.title = 'Careers';
heading={cntCareers.selection_process.heading.heading} heading={cntCareers.selection_process.heading.heading}
subheading={cntCareers.selection_process.heading.subheading} 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> </Wrapper>


{/* Open Positions */} {/* Open Positions */}

+ 40
- 8
frontend/src/pages/ContactPage.jsx Näytä tiedosto

import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useContext } from 'react';
import Contact from '../components/shared/Contact'; import Contact from '../components/shared/Contact';
import { UIContext } from '../context'; import { UIContext } from '../context';
import PageLayout from '../layout/PageLayout'; import PageLayout from '../layout/PageLayout';
import useAnalytics from '../hooks/useAnalytics'; 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(() => { useEffect(() => {
document.title = 'Contact Us'; document.title = 'Contact Us';


return ( return (
<PageLayout> <PageLayout>
{/* {data.SEO ? <ReactHelmet seo={data.SEO} /> : null} */}
<section id="contact" className="h-fit bg-baby-blue dark:bg-dg-primary-1600 mt-90p"> <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> </section>
</PageLayout> </PageLayout>
); );

+ 14
- 21
frontend/src/pages/Home.jsx Näytä tiedosto

import useDataApi from '../hooks/useDataApi'; import useDataApi from '../hooks/useDataApi';
import useAnalytics from '../hooks/useAnalytics'; import useAnalytics from '../hooks/useAnalytics';
import ReactHelmet from '../components/shared/ReactHelmet'; import ReactHelmet from '../components/shared/ReactHelmet';
import { UIContext } from './../context/index';


const api_url = process.env.REACT_APP_API_URL; const api_url = process.env.REACT_APP_API_URL;


'ProcessMobileImg', 'ProcessMobileImg',
'ProcessMobileImg.Image', 'ProcessMobileImg.Image',
'CaseStudies', 'CaseStudies',
'BusinessInquiry',
'BusinessInquiry.image',
'ApplyPosition',
'ApplyPosition.image',
'Map', 'Map',
'SEO', 'SEO',
'SEO.metaSocial', 'SEO.metaSocial',
'SEO.metaImage', 'SEO.metaImage',
'SEO.metaSocial.image', 'SEO.metaSocial.image',
'BusinessInquiry',
'BusinessInquiry.image',
'ApplyPosition',
'ApplyPosition.image',
]; ];


const stringBuilder = () => { const stringBuilder = () => {
} else { } else {
return ( return (
<PageLayout> <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"> <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 */} {/* Landing Section */}
{data ? ( {data ? (
/> />
) : null} ) : null}





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



+ 26
- 1
frontend/src/routes.js Näytä tiedosto

import PrivacyPolicy from "./pages/PrivacyPolicy"; import PrivacyPolicy from "./pages/PrivacyPolicy";
import ProcessPage from "./pages/ProcessPage"; import ProcessPage from "./pages/ProcessPage";
import WorkWithUs from "./pages/WorkWithUs"; import WorkWithUs from "./pages/WorkWithUs";

import EventsTimeline from "./pages/EventsTimeline";
import DiligentLife from "./pages/DiligentLife";
import DiligentMinds from "./pages/DiligentMinds";
const routes = [ const routes = [
{ {
path: '/', path: '/',
title: 'Careers', title: 'Careers',
exact: true, exact: true,
nav: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', path: '/about',

+ 11
- 1
frontend/yarn.lock Näytä tiedosto

"resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz"
"version" "4.2.9" "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": "gzip-size@^6.0.0":
"integrity" "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==" "integrity" "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q=="
"resolved" "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz" "resolved" "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz"
"react-fast-compare" "^3.2.0" "react-fast-compare" "^3.2.0"
"shallowequal" "^1.1.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": "react-is@^16.13.1", "react-is@^16.7.0", "react-is@>= 16.8.0":
"integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
"resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" "resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
optionalDependencies: optionalDependencies:
"fsevents" "^2.3.2" "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==" "integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="
"resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz" "resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
"version" "17.0.2" "version" "17.0.2"

Loading…
Peruuta
Tallenna