| @@ -1,3 +1,4 @@ | |||
| PUBLIC_URL = "https://dilig.net" | |||
| FAST_REFRESH=false | |||
| CHOKIDAR_USEPOLLING=true | |||
| REACT_APP_SERVICE_ID = service_petbzsz | |||
| @@ -7,3 +8,4 @@ REACT_APP_USER_ID = 27spvSZ2Lsf2j8RKw | |||
| REACT_APP_API_URL = "https://websitediligentapi.azurewebsites.net" | |||
| //http://localhost:1337 | |||
| MAILCHIMP_FORM_URL = http://eepurl.com/iaRrv1 | |||
| GOOGLE_TRACKING_ID = "G-PTZC3WLTZ1" | |||
| @@ -1,12 +1,12 @@ | |||
| { | |||
| "name": "frontend", | |||
| "version": "1.0.6", | |||
| "version": "1.0.20", | |||
| "lockfileVersion": 2, | |||
| "requires": true, | |||
| "packages": { | |||
| "": { | |||
| "name": "frontend", | |||
| "version": "1.0.6", | |||
| "version": "1.0.20", | |||
| "dependencies": { | |||
| "@faceless-ui/slider": "^1.1.14", | |||
| "@faceless-ui/window-info": "^2.1.1", | |||
| @@ -1,6 +1,6 @@ | |||
| { | |||
| "name": "frontend", | |||
| "version": "1.0.6", | |||
| "version": "1.1.0", | |||
| "private": true, | |||
| "dependencies": { | |||
| "@faceless-ui/slider": "^1.1.14", | |||
| @@ -25,6 +25,17 @@ | |||
| Learn how to configure a non-root public URL by running `npm run build`. | |||
| --> | |||
| <title>Diligent Software</title> | |||
| <!-- Google tag (gtag.js) --> | |||
| <!-- <script async src='https://www.googletagmanager.com/gtag/js?id=G-PTZC3WLTZ1'></script> | |||
| <script> | |||
| window.dataLayer = window.dataLayer || []; | |||
| function gtag() { dataLayer.push(arguments); } | |||
| gtag('js', new Date()); | |||
| gtag('config', 'G-PTZC3WLTZ1'); | |||
| </script> --> | |||
| </head> | |||
| <body> | |||
| <noscript>You need to enable JavaScript to run this app.</noscript> | |||
| @@ -1,3 +1,4 @@ | |||
| # https://www.robotstxt.org/robotstxt.html | |||
| User-agent: * | |||
| Disallow: | |||
| Sitemap: https://www.dilig.net/sitemap.txt | |||
| @@ -0,0 +1,15 @@ | |||
| https://www.dilig.net/ | |||
| https://www.dilig.net/portfolio | |||
| https://www.dilig.net/casestudybi | |||
| https://www.dilig.net/casestudystrata | |||
| https://www.dilig.net/casestudyfinancial | |||
| https://www.dilig.net/casestudyticketing | |||
| https://www.dilig.net/casestudycentralized | |||
| https://www.dilig.net/casestudyresource | |||
| https://www.dilig.net/services | |||
| https://www.dilig.net/about | |||
| https://www.dilig.net/post | |||
| https://www.dilig.net/process | |||
| https://www.dilig.net/contact | |||
| https://www.dilig.net/privacypolicy | |||
| https://www.dilig.net/openday | |||
| @@ -1,73 +1,54 @@ | |||
| import React, { useEffect } from 'react'; | |||
| 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 Home from './pages/Home'; | |||
| import Portfolio from './pages/Portfolio'; | |||
| import Services from './pages/Services'; | |||
| import Careers from './pages/Careers'; | |||
| import About from './pages/About'; | |||
| import BlogPost from './components/BlogPost'; | |||
| import Footer from './components/shared/Footer'; | |||
| import { useRef, useState } from 'react'; | |||
| import ProcessPage from './pages/ProcessPage'; | |||
| import ContactPage from './pages/ContactPage'; | |||
| import CaseStudyBI from './pages/CaseStudyBI'; | |||
| import CaseStudyFinantial from './pages/CaseStudyFinantial'; | |||
| import CaseStudyTicketing from './pages/CaseStudyTicketing'; | |||
| import CaseStudyCentralized from './pages/CaseStudyCentralized'; | |||
| import CaseStudyResource from './pages/CaseStudyResource'; | |||
| import CaseStudyStrata from './pages/CaseStudyStrata'; | |||
| import PrivacyPolicy from './pages/PrivacyPolicy'; | |||
| import Loader from './components/shared/Loader'; | |||
| import ScrollToTop from './components/root/ScrollToTop'; | |||
| import routes from './routes'; | |||
| const Home = lazy(() => import('./pages/Home')); | |||
| const Portfolio = lazy(() => import('./pages/Portfolio')); | |||
| const Services = lazy(() => import('./pages/Services')); | |||
| const Careers = lazy(() => import('./pages/Careers')); | |||
| const About = lazy(() => import('./pages/About')); | |||
| const BlogPost = lazy(() => import('./components/BlogPost')); | |||
| const ProcessPage = lazy(() => import('./pages/ProcessPage')); | |||
| const ContactPage = lazy(() => import('./pages/ContactPage')); | |||
| const CaseStudyBI = lazy(() => import('./pages/CaseStudyBI')); | |||
| const CaseStudyFinantial = lazy(() => import('./pages/CaseStudyFinantial')); | |||
| const CaseStudyTicketing = lazy(() => import('./pages/CaseStudyTicketing')); | |||
| const CaseStudyCentralized = lazy(() => import('./pages/CaseStudyCentralized')); | |||
| const CaseStudyResource = lazy(() => import('./pages/CaseStudyResource')); | |||
| const CaseStudyStrata = lazy(() => import('./pages/CaseStudyStrata')); | |||
| const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy')); | |||
| const WorkWithUs = lazy(() => import('./pages/WorkWithUs')); | |||
| // Navigation Links | |||
| const links = [ | |||
| { | |||
| name: 'Case Studies', | |||
| description: '', | |||
| href: '/portfolio', | |||
| icon: '', | |||
| }, | |||
| { | |||
| name: 'Process', | |||
| description: '', | |||
| href: '/process', | |||
| icon: '', | |||
| }, | |||
| { | |||
| name: 'Careers', | |||
| description: '', | |||
| href: '/careers', | |||
| icon: '', | |||
| }, | |||
| { | |||
| name: 'About us', | |||
| description: '', | |||
| href: '/about', | |||
| icon: '', | |||
| }, | |||
| ]; | |||
| const links = routes.filter(item => item.nav === true); | |||
| function App() { | |||
| function App() { | |||
| //tabs for contact form | |||
| const [tab, setTab] = useState(true); | |||
| const [tabTitle, setTabTitle] = useState('Tell Us About Your Idea!'); | |||
| const link = useNavigate() | |||
| const link = useNavigate(); | |||
| //scroll to Contact segment | |||
| const forwardedRef = useRef(null); | |||
| //initialize analytics page tracking | |||
| //usePageTracking(); | |||
| //scroll to Contact fn | |||
| function scrollToView(event) { | |||
| event.preventDefault(); | |||
| if (forwardedRef) { | |||
| forwardedRef.current.scrollIntoView({ behavior: 'smooth' }); | |||
| } | |||
| else { | |||
| } else { | |||
| link('/contact'); | |||
| } | |||
| } | |||
| @@ -83,44 +64,32 @@ function App() { | |||
| } | |||
| return ( | |||
| <div> | |||
| <ScrollToTop /> | |||
| <Navigation | |||
| links={links} | |||
| scrollToView={scrollToView} | |||
| activeLinks={activeLinks} | |||
| forwardedRef={forwardedRef} | |||
| ></Navigation> | |||
| <Routes> | |||
| <Route | |||
| exact | |||
| path="/" | |||
| element={ | |||
| <Home | |||
| tab={tab} | |||
| tabTitle={tabTitle} | |||
| setTab={setTab} | |||
| setTabTitle={setTabTitle} | |||
| forwardedRef={forwardedRef} | |||
| /> | |||
| } | |||
| /> | |||
| <Route exact path="/portfolio" element={<Portfolio />} /> | |||
| <Route exact path="/casestudybi" element={<CaseStudyBI />} /> | |||
| <Route exact path="/casestudystrata" element={<CaseStudyStrata />} /> | |||
| <Route exact path="/casestudyfinancial" element={<CaseStudyFinantial />} /> | |||
| <Route exact path="/casestudyticketing" element={<CaseStudyTicketing />} /> | |||
| <Route exact path="/casestudycentralized" element={<CaseStudyCentralized />} /> | |||
| <Route exact path="/casestudyresource" element={<CaseStudyResource />} /> | |||
| <Route exact path="/services" element={<Services />} /> | |||
| <Route exact path="/careers" element={<Careers />} /> | |||
| <Route exact path="/about" element={<About />} /> | |||
| <Route exact path="/post" element={<BlogPost />} /> | |||
| <Route exact path="/process" element={<ProcessPage />} /> | |||
| <Route exact path="/contact" element={<ContactPage />} /> | |||
| <Route exact path="/privacypolicy" element={<PrivacyPolicy />} /> | |||
| </Routes> | |||
| <Suspense fallback={<Loader />}> | |||
| <Routes> | |||
| <Route exact path="/" element={<Home />}/> | |||
| <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> | |||
| <Footer | |||
| links={links} | |||
| @@ -128,9 +97,7 @@ function App() { | |||
| scrollToView={scrollToView} | |||
| forwardedRef={forwardedRef} | |||
| /> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,6 @@ | |||
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M9 22H15C20 22 22 20 22 15V9C22 4 20 2 15 2H9C4 2 2 4 2 9V15C2 20 4 22 9 22Z" stroke="#FAFAFA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M9 11.5098L12 14.5098L15 11.5098" stroke="#FAFAFA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M12 14.5098V6.50977" stroke="#FAFAFA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M6 16.5098C9.89 17.8098 14.11 17.8098 18 16.5098" stroke="#FAFAFA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,7 @@ | |||
| <svg width="80" height="81" viewBox="0 0 80 81" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M56.334 73.8327H23.6673C18.0007 73.8327 13.334 69.1993 13.334 63.4993V17.4994C13.334 11.8327 17.9673 7.16602 23.6673 7.16602H56.334C62.0006 7.16602 66.6673 11.7994 66.6673 17.4994V63.4993C66.6673 69.1993 62.034 73.8327 56.334 73.8327Z" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M61.6673 43.8327H18.334C15.5673 43.8327 13.334 41.5993 13.334 38.8327V32.166C13.334 29.3993 15.5673 27.166 18.334 27.166H61.6673C64.434 27.166 66.6673 29.3993 66.6673 32.166V38.8327C66.6673 41.5993 64.434 43.8327 61.6673 43.8327Z" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M28.3144 59.5007H28.3443" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M51.6484 59.5007H51.6783" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M31.666 17.166H48.3327" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,8 @@ | |||
| <svg width="80" height="81" viewBox="0 0 80 81" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M60.134 45.6673C58.734 47.0339 57.934 49.0006 58.134 51.1006C58.434 54.7006 61.734 57.3339 65.334 57.3339H71.6673V61.3006C71.6673 68.2006 66.034 73.834 59.134 73.834H25.434C26.4673 72.9673 27.3673 71.9006 28.0673 70.7006C29.3006 68.7006 30.0007 66.334 30.0007 63.834C30.0007 56.4673 24.034 50.5007 16.6673 50.5007C13.534 50.5007 10.634 51.6007 8.33398 53.434V38.8673C8.33398 31.9674 13.9673 26.334 20.8673 26.334H59.134C66.034 26.334 71.6673 31.9674 71.6673 38.8673V43.6674H64.934C63.0673 43.6674 61.3673 44.4006 60.134 45.6673Z" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M8.33398 41.8663V26.6332C8.33398 22.6665 10.7673 19.133 14.4673 17.733L40.934 7.73305C45.0673 6.16638 49.5007 9.23314 49.5007 13.6665V26.3331" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M75.1967 47.0678V53.9347C75.1967 55.768 73.73 57.2679 71.8633 57.3346H65.33C61.73 57.3346 58.43 54.7012 58.13 51.1012C57.93 49.0012 58.73 47.0346 60.13 45.6679C61.3633 44.4012 63.0633 43.668 64.93 43.668H71.8633C73.73 43.7346 75.1967 45.2345 75.1967 47.0678Z" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M23.334 40.5H46.6673" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M30.0007 63.8333C30.0007 66.3333 29.3006 68.7 28.0673 70.7C27.3673 71.9 26.4673 72.9667 25.434 73.8333C23.1007 75.9333 20.034 77.1667 16.6673 77.1667C11.8007 77.1667 7.56732 74.5667 5.26732 70.7C4.03399 68.7 3.33398 66.3333 3.33398 63.8333C3.33398 59.6333 5.26732 55.8667 8.33398 53.4333C10.634 51.6 13.534 50.5 16.6673 50.5C24.034 50.5 30.0007 56.4667 30.0007 63.8333Z" stroke="#902890" stroke-width="4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M11.4727 63.8311L14.7726 67.131L21.8726 60.5645" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,7 @@ | |||
| <svg width="80" height="81" viewBox="0 0 80 81" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M6.66602 73.834H73.3326" stroke="#902890" stroke-width="4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M56.6667 7.16602H23.3333C13.3333 7.16602 10 13.1327 10 20.4993V73.8326H70V20.4993C70 13.1327 66.6667 7.16602 56.6667 7.16602Z" stroke="#902890" stroke-width="4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M46.8668 50.5H33.1001C31.4001 50.5 29.9668 51.9 29.9668 53.6333V73.8333H49.9668V53.6333C50.0001 51.9 48.6001 50.5 46.8668 50.5Z" stroke="#902890" stroke-width="4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M40 20.5V37.1667" stroke="#902890" stroke-width="4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M31.666 28.834H48.3327" stroke="#902890" stroke-width="4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,5 @@ | |||
| <svg width="80" height="81" viewBox="0 0 80 81" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M33.4991 8.93296L13.4324 22.033C6.99909 26.233 6.99909 35.633 13.4324 39.833L33.4991 52.933C37.0991 55.2996 43.0324 55.2996 46.6324 52.933L66.5991 39.833C72.9991 35.633 72.9991 26.2663 66.5991 22.0663L46.6324 8.9663C43.0324 6.5663 37.0991 6.5663 33.4991 8.93296Z" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M18.7658 44.0996L18.7324 59.7329C18.7324 63.9663 21.9991 68.4996 25.9991 69.8329L36.6324 73.3663C38.4658 73.9663 41.4991 73.9663 43.3658 73.3663L53.9991 69.8329C57.9991 68.4996 61.2658 63.9663 61.2658 59.7329V44.2663" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M71.334 50.5V30.5" stroke="#902890" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -1,28 +1,33 @@ | |||
| import React, { useEffect, useState } from "react"; | |||
| import Grid from "../layout/Grid"; | |||
| import PortfolioCard from "./PortfolioCard"; | |||
| import React, { useEffect, useState } from 'react'; | |||
| import Grid from '../layout/Grid'; | |||
| import PortfolioCard from './PortfolioCard'; | |||
| const api_url = process.env.REACT_APP_API_URL; | |||
| const CardsGrid = ({data}) => { | |||
| const [state, setState] = useState(data); | |||
| const CardsGrid = ({ data }) => { | |||
| const [state, setState] = useState(data); | |||
| useEffect(() => { | |||
| setState(data); | |||
| }, [data]); | |||
| useEffect(() => { | |||
| setState(data); | |||
| }, [data]); | |||
| return ( | |||
| <div className="grid overflow-visible grid-cols-1 md:grid-cols-2 lg:grid-cols-3 auto-rows-auto gap-8"> | |||
| { state && | |||
| state.length > 0 && | |||
| state.map ((item, index) => ( | |||
| // item.attributes.img.data != null && | |||
| // <PortfolioCard key={index} title={item.attributes.heading} img={api_url + item.attributes.img.data.attributes.formats.small.url} isLarge={item.attributes.IsLarge} /> | |||
| <PortfolioCard key={index} title={item.title} isLarge={false} link={item.link} img={item.imgUrl} /> | |||
| )) | |||
| } | |||
| </div> | |||
| ) | |||
| } | |||
| export default CardsGrid; | |||
| return ( | |||
| <div className="grid overflow-visible grid-cols-1 md:grid-cols-2 lg:grid-cols-3 auto-rows-auto gap-8"> | |||
| {state && | |||
| state.length > 0 && | |||
| state.map((item, index) => ( | |||
| // item.attributes.img.data != null && | |||
| // <PortfolioCard key={index} title={item.attributes.heading} img={api_url + item.attributes.img.data.attributes.formats.small.url} isLarge={item.attributes.IsLarge} /> | |||
| <PortfolioCard | |||
| key={index} | |||
| title={item.title} | |||
| alt={item.alt} | |||
| isLarge={false} | |||
| link={item.link} | |||
| img={item.imgUrl} | |||
| /> | |||
| ))} | |||
| </div> | |||
| ); | |||
| }; | |||
| export default CardsGrid; | |||
| @@ -1,41 +1,42 @@ | |||
| import React from 'react' | |||
| import PropTypes from 'prop-types' | |||
| import React from 'react'; | |||
| import PropTypes from 'prop-types'; | |||
| import net from './../assets/icons/net.svg'; | |||
| const _card = { | |||
| role: ".Net Developer", | |||
| shortDetails: "All levels of experience", | |||
| } | |||
| role: '.Net Developer', | |||
| shortDetails: 'All levels of experience', | |||
| }; | |||
| const CareerCard = ({card ,setExpanded, setExpandedCard}) => { | |||
| const CareerCard = ({ card, setExpanded, setExpandedCard }) => { | |||
| return ( | |||
| <div onClick={() => {setExpanded(true);setExpandedCard(card)}} className={'card max-w-[360px]'}> | |||
| <div | |||
| onClick={() => { | |||
| setExpanded(true); | |||
| setExpandedCard(card); | |||
| }} | |||
| className={'card max-w-[360px]'} | |||
| > | |||
| <img | |||
| src={net} | |||
| className={ | |||
| 'ml-auto mr-auto block w-[70px] bg-baby-blue text-dark-gray' | |||
| } | |||
| alt=".NET" | |||
| className={'ml-auto mr-auto block w-[70px] bg-baby-blue text-dark-gray'} | |||
| /> | |||
| <h3 className={'mt-6 font-semibold text-2xl'}> | |||
| {card.role} | |||
| </h3> | |||
| <h3 className={'mt-6 font-semibold text-2xl'}>{card.role}</h3> | |||
| <p className={'mt-6 text-sm'}>{_card.shortDetails}</p> | |||
| <a | |||
| href={'#'} | |||
| className={'min-w-max btn btn_primary mt-8 opacity-0 transition-all group-hover:opacity-100 group-hover:transition-all' | |||
| 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> | |||
| ) | |||
| } | |||
| ); | |||
| }; | |||
| CareerCard.propTypes = { | |||
| card: PropTypes.object, | |||
| } | |||
| card: PropTypes.object, | |||
| }; | |||
| export default CareerCard | |||
| export default CareerCard; | |||
| @@ -1,30 +1,30 @@ | |||
| import React from "react"; | |||
| import { motion } from "framer-motion"; | |||
| import LandingSVGv2 from "./shared/graphics/LandingSVG-v2"; | |||
| import HiringWidget from "./HiringWidget"; | |||
| import Wrapper from "../layout/Wrapper"; | |||
| import OpenDayBanner from "./OpenDayBanner"; | |||
| import React from 'react'; | |||
| import { motion } from 'framer-motion'; | |||
| import LandingSVGv2 from './shared/graphics/LandingSVG-v2'; | |||
| import HiringWidget from './HiringWidget'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import OpenDayBanner from './OpenDayBanner'; | |||
| const _data = { | |||
| cto: "contact us" | |||
| } | |||
| cto: 'contact us', | |||
| }; | |||
| const numbers = [ | |||
| { | |||
| value: 90, | |||
| static: '+', | |||
| title: 'Employees' | |||
| title: 'Employees', | |||
| }, | |||
| { | |||
| value: '20', | |||
| static: '+', | |||
| title: 'Projects' | |||
| title: 'Projects', | |||
| }, | |||
| { | |||
| value: '100', | |||
| static: '%', | |||
| title: 'Client-Retention' | |||
| } | |||
| ] | |||
| title: 'Client-Retention', | |||
| }, | |||
| ]; | |||
| const Landing = ({ data }) => { | |||
| return ( | |||
| @@ -36,10 +36,7 @@ const Landing = ({ data }) => { | |||
| initial={{ y: 60, opacity: 0 }} | |||
| whileInView={{ y: 0, opacity: 1 }} | |||
| transition={{ duration: 0.5, ease: 'easeOut' }} | |||
| > | |||
| {/* <img src={bg_home} alt="Diligent Software's Animation" width="700" /> */} | |||
| {/* <LandingSVG /> */} | |||
| @@ -65,7 +62,6 @@ const Landing = ({ data }) => { | |||
| {_data.cto} | |||
| </a> | |||
| </div> | |||
| </motion.section> | |||
| <motion.section | |||
| id="status-numbers" | |||
| @@ -76,25 +72,17 @@ const Landing = ({ data }) => { | |||
| > | |||
| {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> | |||
| <p className="display-number text-center"> | |||
| {item.value} | |||
| {item.static} | |||
| </p> | |||
| <h3 className="number-title text-center">{item.title}</h3> | |||
| </div> | |||
| ))} | |||
| </motion.section> | |||
| </div> | |||
| </Wrapper> | |||
| ) | |||
| } | |||
| ); | |||
| }; | |||
| export default Landing; | |||
| export default Landing; | |||
| @@ -3,19 +3,19 @@ import './../App.css' | |||
| export default function OpenDayBanner() { | |||
| const [isHover,setHover] = useState(false); | |||
| const [isHover, setHover] = useState(false); | |||
| return ( | |||
| <a href="/openday"> | |||
| <div className={"bg-[#7274AB] size-07 absolute left-[-25px] top-[-50px] rounded-full md:top-[-15px] md:left-0 transition-all px-6 py-2 b-50"+(isHover ? " md:scale-125" : "")} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}> | |||
| <div className={"relative flex justify-center items-center"}> | |||
| <h2 className={"uppercase text-sm z-10 text-white transition-all"}>Open Day - October 26 !</h2> | |||
| </div> | |||
| <div className={"bg-[#7274AB] size-07 absolute left-[-25px] top-[-50px] rounded-full md:top-[-15px] md:left-0 transition-all px-6 py-2 b-50" + (isHover ? " md:scale-125" : "")} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}> | |||
| <div className={"relative flex justify-center items-center"}> | |||
| <h2 className={"uppercase text-sm z-10 text-white transition-all"}>Open Day - October 26 !</h2> | |||
| </div> | |||
| </div> | |||
| </a> | |||
| </a> | |||
| ) | |||
| } | |||
| @@ -1,25 +1,23 @@ | |||
| import React, { useEffect, useState } from "react"; | |||
| import { useNavigate } from "react-router-dom"; | |||
| import React, { useEffect, useState } from 'react'; | |||
| import { useNavigate } from 'react-router-dom'; | |||
| const api_url = process.env.REACT_APP_API_URL; | |||
| const PortfolioCard = ({title, isLarge, link, img}) => { | |||
| const linkTo = useNavigate(); | |||
| const PortfolioCard = ({ title, isLarge, link, img, alt }) => { | |||
| const linkTo = useNavigate(); | |||
| useEffect(() => { | |||
| //console.log(isLarge); | |||
| }) | |||
| 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}> | |||
| <img src={img} className={'mb-12 mx-auto self-center'}></img> | |||
| <h3 className="h3-heading">{title}</h3> | |||
| <button className="btn text-dg-secondary mt-4">Read More</button> | |||
| </a> | |||
| ) | |||
| } | |||
| return ( | |||
| // <div className={"card box" + (isLarge ? ' col-span-2' : '')}> | |||
| <a className={'card box my-2 flex- flex-col items-center'} href={link}> | |||
| <img src={img} alt={alt} className={'mb-12 mx-auto self-center'}></img> | |||
| <h3 className="h3-heading">{title}</h3> | |||
| <button className="btn text-dg-secondary mt-4">Read More</button> | |||
| </a> | |||
| ); | |||
| }; | |||
| export default PortfolioCard; | |||
| export default PortfolioCard; | |||
| @@ -1,68 +1,71 @@ | |||
| import React from 'react' | |||
| import { useNavigate } from 'react-router-dom' | |||
| import Wrapper from '../layout/Wrapper' | |||
| import PageTitle from './shared/PageTitle' | |||
| import ProcessCard from './shared/ProcessCard' | |||
| import ProcessCardsWrapper from './shared/ProcessCardWrapper' | |||
| import React from 'react'; | |||
| import { useNavigate } from 'react-router-dom'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import PageTitle from './shared/PageTitle'; | |||
| import ProcessCard from './shared/ProcessCard'; | |||
| import ProcessCardsWrapper from './shared/ProcessCardWrapper'; | |||
| const _data = { | |||
| cards: [ | |||
| { | |||
| id: 0, | |||
| title: 'Bi Healthcare Solution System', | |||
| imgUrl: | |||
| 'https://lh6.googleusercontent.com/D7N87i3udAln4YBp5SbaSI-9r2pVnnT5K2VT6p0G3dQanVgTMC2tdgz71PWOYco-7yQ=w2400', | |||
| link: '/casestudybi', | |||
| }, | |||
| { | |||
| id: 1, | |||
| title: 'Resource Planning System', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/HLOh5coHfcEgDuftj1pOA9f1865xiIom5vyxTWNMKqMiivxL8Lg4c9ACzbfYYUdeuqQ=w2400', | |||
| link: '/casestudyresource', | |||
| }, | |||
| { | |||
| id: 2, | |||
| title: 'Ticketing System for Passengers', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/f_G0H0C_qLHhsU8PBj6uTkNigzKiXzd24B_pgJ6UqVmBKlU2Lyxv2r5lf6uvY9d_0PY=w2400', | |||
| link: '/casestudyticketing', | |||
| }, | |||
| ], | |||
| } | |||
| cards: [ | |||
| { | |||
| id: 0, | |||
| title: 'BI Healthcare Solution System', | |||
| imgUrl: | |||
| 'https://lh6.googleusercontent.com/D7N87i3udAln4YBp5SbaSI-9r2pVnnT5K2VT6p0G3dQanVgTMC2tdgz71PWOYco-7yQ=w2400', | |||
| alt: 'BI Healthcare Solution System', | |||
| link: '/casestudybi', | |||
| }, | |||
| { | |||
| id: 1, | |||
| title: 'Resource Planning System', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/HLOh5coHfcEgDuftj1pOA9f1865xiIom5vyxTWNMKqMiivxL8Lg4c9ACzbfYYUdeuqQ=w2400', | |||
| alt: 'Resource Planning System', | |||
| link: '/casestudyresource', | |||
| }, | |||
| { | |||
| id: 2, | |||
| title: 'Ticketing System for Passengers', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/f_G0H0C_qLHhsU8PBj6uTkNigzKiXzd24B_pgJ6UqVmBKlU2Lyxv2r5lf6uvY9d_0PY=w2400', | |||
| alt: 'Ticketing System for Passengers', | |||
| link: '/casestudyticketing', | |||
| }, | |||
| ], | |||
| }; | |||
| function PortfolioSection() { | |||
| const linkTo = useNavigate(); | |||
| const linkTo = useNavigate(); | |||
| return ( | |||
| <Wrapper padding={' py-90p'} bg> | |||
| <div className="py-32p"> | |||
| <PageTitle left heading={'Case Studies'} subheading={'our Work'} /> | |||
| </div> | |||
| return ( | |||
| <Wrapper padding={" py-90p"} bg> | |||
| <div className='py-32p'> | |||
| <PageTitle left heading={"Case Studies"} subheading={"our Work"} /> | |||
| </div> | |||
| <div className='flex flex-col lg:flex-row justify-center items-center lg:justify-between gap-8'> | |||
| {_data.cards.map((item,index) => ( | |||
| <a className={"card max-w-780p box my-2 flex flex-col items-center"} href={item.link} key={index}> | |||
| <img src={item.imgUrl} className={'mb-12'}></img> | |||
| <div className="flex flex-col lg:flex-row justify-center items-center lg:justify-between gap-8"> | |||
| {_data.cards.map((item, index) => ( | |||
| <a | |||
| className={'card max-w-780p box my-2 flex flex-col items-center'} | |||
| href={item.link} | |||
| key={index} | |||
| > | |||
| <img src={item.imgUrl} alt={item.alt} className={'mb-12'}></img> | |||
| <h3 className="h3-heading">{item.title}</h3> | |||
| <button className="btn text-dg-secondary mt-4">Read More</button> | |||
| </a> | |||
| </a> | |||
| ))} | |||
| </div> | |||
| <div className='flex justify-center text-center'> | |||
| <button className="btn text-dg-secondary mt-4" onClick={()=>linkTo('/portfolio')}>See More...</button> | |||
| </div> | |||
| </Wrapper> | |||
| ) | |||
| </div> | |||
| <div className="flex justify-center text-center"> | |||
| <button | |||
| className="btn text-dg-secondary mt-4" | |||
| onClick={() => linkTo('/portfolio')} | |||
| > | |||
| See More... | |||
| </button> | |||
| </div> | |||
| </Wrapper> | |||
| ); | |||
| } | |||
| export default PortfolioSection; | |||
| export default PortfolioSection; | |||
| @@ -22,7 +22,7 @@ const ProcessSection = () => { | |||
| const windowInfo = useWindowSize(); | |||
| useEffect(() => { | |||
| console.log(windowInfo.width); | |||
| //console.log(windowInfo.width); | |||
| if (windowInfo.width < 1000) | |||
| setIsMobile(true); | |||
| else | |||
| @@ -1,83 +1,117 @@ | |||
| import React, { Fragment, useEffect } from "react"; | |||
| import useScreenDimensions from "../hooks/useScreenDimensions"; | |||
| import Wrapper from "../layout/Wrapper"; | |||
| import FMCarousel from "./shared/FMCarousel"; | |||
| import HorizontalScroller from "./shared/HorizontalScroller"; | |||
| import PageHeading from "./shared/PageHeading"; | |||
| import PageTitle from "./shared/PageTitle"; | |||
| import TestimonialCard from "./shared/TestimonialCard"; | |||
| import Boza from "./../assets/boza.jpg" | |||
| import React, { Fragment, useEffect } from 'react'; | |||
| import useScreenDimensions from '../hooks/useScreenDimensions'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import FMCarousel from './shared/FMCarousel'; | |||
| import HorizontalScroller from './shared/HorizontalScroller'; | |||
| import PageHeading from './shared/PageHeading'; | |||
| import PageTitle from './shared/PageTitle'; | |||
| import TestimonialCard from './shared/TestimonialCard'; | |||
| import Boza from './../assets/boza.jpg'; | |||
| import Peter from './../assets/peter1.png'; | |||
| import ns from './../assets/ns.png'; | |||
| const _data = { | |||
| heading: "What Our Clients Said", | |||
| subheading: "Testimonials", | |||
| cards: [ | |||
| { | |||
| clientName: "Peter Custer", | |||
| paragraph: "Diligent is a highly valuable resource in GBI's arsenal. Reliable, versatile and skilled. They are a true representation of their company name - following through the entire process of any task we challenged them with, meeting, and exceeding, expectations regardless of the project environment.", | |||
| clientRole: "CTO @ Gold Bullion International", | |||
| clientImg: Peter, | |||
| heading: 'What Our Clients Said', | |||
| subheading: 'Testimonials', | |||
| cards: [ | |||
| { | |||
| clientName: 'Peter Custer', | |||
| paragraph: | |||
| "Diligent is a highly valuable resource in GBI's arsenal. Reliable, versatile and skilled. They are a true representation of their company name - following through the entire process of any task we challenged them with, meeting, and exceeding, expectations regardless of the project environment.", | |||
| clientRole: 'CTO @ Gold Bullion International', | |||
| clientImg: Peter, | |||
| alt: 'Peter Custer - CTO @ Gold Bullion International', | |||
| }, | |||
| { | |||
| clientName: 'Božidar Ignjatović', | |||
| paragraph: | |||
| "Diligent team is my old and reliable partner. We've been working together for more than a decade. They are highly skilled professionals for any assigned job. Do not hesitate if you need support, Diligent brings additional value. They are not only tech team, they'll be partners to your business as they were for ours!", | |||
| clientRole: 'BadinSoft Co-Founder, CEO', | |||
| clientImg: Boza, | |||
| alt: 'Božidar Ignjatović - BadinSoft Co-Founder, CEO', | |||
| }, | |||
| { | |||
| clientName: 'Niš Ekspres', | |||
| paragraph: `Our industry is susceptible, requiring the Information System to be reliable and flexible. Diligent helped us to build and integrate several parts of the existing Information System with multiple integration points and enabled fieldwork. Be assured that you can always count on the highest performance from Diligent, "around-the-clock" support and have a partner to your business.`, | |||
| clientRole: '', | |||
| clientImg: ns, | |||
| alt: 'Niš Ekspres', | |||
| }, | |||
| ], | |||
| }; | |||
| }, | |||
| { | |||
| clientName: "Božidar Ignjatović", | |||
| paragraph: "Diligent team is my old and reliable partner. We've been working together for more than a decade. They are highly skilled professionals for any assigned job. Do not hesitate if you need support, Diligent brings additional value. They are not only tech team, they'll be partners to your business as they were for ours!", | |||
| clientRole: "BadinSoft Co-Founder, CEO", | |||
| clientImg: Boza, | |||
| export default function Testimonials({ noTitle }) { | |||
| const screenSize = useScreenDimensions(); | |||
| }, | |||
| { | |||
| clientName: "Niš Ekspres", | |||
| paragraph: `Our industry is susceptible, requiring the Information System to be reliable and flexible. Diligent helped us to build and integrate several parts of the existing Information System with multiple integration points and enabled fieldwork. Be assured that you can always count on the highest performance from Diligent, "around-the-clock" support and have a partner to your business.`, | |||
| clientRole: "", | |||
| clientImg: ns, | |||
| return ( | |||
| <Wrapper padding={' py-90p'}> | |||
| <div className="flex flex-col gap-32p md:gap-90p w-full"> | |||
| {!noTitle && ( | |||
| <div className="w-full"> | |||
| <PageTitle heading={_data.heading} subheading={_data.subheading} left /> | |||
| </div> | |||
| )} | |||
| }, | |||
| ] | |||
| } | |||
| export default function Testimonials() { | |||
| const screenSize = useScreenDimensions(); | |||
| return ( | |||
| <Wrapper padding={" py-90p"}> | |||
| <div className="flex flex-col gap-32p md:gap-90p w-full"> | |||
| <div className="w-full"> | |||
| <PageTitle heading={_data.heading} subheading={_data.subheading} left /> | |||
| </div> | |||
| <div className="relative w-full h-[500px] overflow-hidden"> | |||
| {screenSize.width > 1000 ? | |||
| <div className="relative w-full h-[500px] overflow-hidden"> | |||
| {screenSize.width > 1000 ? ( | |||
| <FMCarousel> | |||
| <div className="flex"> | |||
| <TestimonialCard clientName={_data.cards[0].clientName} clientRole={_data.cards[0].clientRole} clientImg={_data.cards[0].clientImg} paragraph={_data.cards[0].paragraph}/> | |||
| <TestimonialCard clientName={_data.cards[1].clientName} clientRole={_data.cards[1].clientRole} clientImg={_data.cards[1].clientImg} paragraph={_data.cards[1].paragraph}/> | |||
| </div> | |||
| <div className="flex"> | |||
| <TestimonialCard clientName={_data.cards[2].clientName} clientRole={_data.cards[2].clientRole} clientImg={_data.cards[2].clientImg} paragraph={_data.cards[2].paragraph}/> | |||
| </div> | |||
| {/* | |||
| <div className="flex"> | |||
| <TestimonialCard | |||
| clientName={_data.cards[0].clientName} | |||
| clientRole={_data.cards[0].clientRole} | |||
| clientImg={_data.cards[0].clientImg} | |||
| imageAlt={_data.cards[0].alt} | |||
| paragraph={_data.cards[0].paragraph} | |||
| /> | |||
| <TestimonialCard | |||
| clientName={_data.cards[1].clientName} | |||
| clientRole={_data.cards[1].clientRole} | |||
| clientImg={_data.cards[1].clientImg} | |||
| imageAlt={_data.cards[1].alt} | |||
| paragraph={_data.cards[1].paragraph} | |||
| /> | |||
| </div> | |||
| <div className="flex"> | |||
| <TestimonialCard | |||
| clientName={_data.cards[2].clientName} | |||
| clientRole={_data.cards[2].clientRole} | |||
| clientImg={_data.cards[2].clientImg} | |||
| imageAlt={_data.cards[2].alt} | |||
| paragraph={_data.cards[2].paragraph} | |||
| /> | |||
| </div> | |||
| {/* | |||
| <TestimonialCard/> | |||
| <TestimonialCard/> | |||
| */} | |||
| </FMCarousel> | |||
| : | |||
| <FMCarousel> | |||
| <TestimonialCard clientName={_data.cards[0].clientName} clientRole={_data.cards[0].clientRole} clientImg={_data.cards[0].clientImg} paragraph={_data.cards[0].paragraph}/> | |||
| <TestimonialCard clientName={_data.cards[1].clientName} clientRole={_data.cards[1].clientRole} clientImg={_data.cards[1].clientImg} paragraph={_data.cards[1].paragraph}/> | |||
| <TestimonialCard clientName={_data.cards[2].clientName} clientRole={_data.cards[2].clientRole} clientImg={_data.cards[2].clientImg} paragraph={_data.cards[2].paragraph}/> | |||
| </FMCarousel> | |||
| } | |||
| </div> | |||
| </div> | |||
| </Wrapper> | |||
| ) | |||
| } | |||
| */} | |||
| </FMCarousel> | |||
| ) : ( | |||
| <FMCarousel> | |||
| <TestimonialCard | |||
| clientName={_data.cards[0].clientName} | |||
| clientRole={_data.cards[0].clientRole} | |||
| clientImg={_data.cards[0].clientImg} | |||
| imageAlt={_data.cards[0].alt} | |||
| paragraph={_data.cards[0].paragraph} | |||
| /> | |||
| <TestimonialCard | |||
| clientName={_data.cards[1].clientName} | |||
| clientRole={_data.cards[1].clientRole} | |||
| clientImg={_data.cards[1].clientImg} | |||
| imageAlt={_data.cards[1].alt} | |||
| paragraph={_data.cards[1].paragraph} | |||
| /> | |||
| <TestimonialCard | |||
| clientName={_data.cards[2].clientName} | |||
| clientRole={_data.cards[2].clientRole} | |||
| clientImg={_data.cards[2].clientImg} | |||
| imageAlt={_data.cards[2].alt} | |||
| paragraph={_data.cards[2].paragraph} | |||
| /> | |||
| </FMCarousel> | |||
| )} | |||
| </div> | |||
| </div> | |||
| </Wrapper> | |||
| ); | |||
| } | |||
| @@ -1,24 +1,27 @@ | |||
| import React from 'react' | |||
| import PropTypes from 'prop-types' | |||
| import {ReactComponent as BrakLine} from './../assets/BreakLine.svg'; | |||
| import React from 'react'; | |||
| import PropTypes from 'prop-types'; | |||
| import { ReactComponent as BrakLine } from './../assets/BreakLine.svg'; | |||
| const TimelineCard = ({title, subtitle, paragraph, id}) => { | |||
| const TimelineCard = ({ title, subtitle, paragraph, id }) => { | |||
| const left = id % 2 === 0; | |||
| const left = (id) % 2 === 0; | |||
| return ( | |||
| <div | |||
| className={ | |||
| 'max-w-[450px] rounded-[32px] card-no-hover relative self-center' + | |||
| (left ? ' lg:self-start' : ' lg:self-end') | |||
| } | |||
| > | |||
| <div className="flex flex-col justify-start text-left gap-8p"> | |||
| <h4 className="subtitle-card-italic-gray">{subtitle}</h4> | |||
| <h3 className="title-card capitalize text-dg-primary-900">{title}</h3> | |||
| <BrakLine className="my-[28px]" /> | |||
| <p className="paragraph">{paragraph}</p> | |||
| </div> | |||
| </div> | |||
| ); | |||
| }; | |||
| return ( | |||
| <div className={"max-w-[450px] rounded-[32px] card-no-hover relative self-center" + (left ? " lg:self-start" : " lg:self-end")}> | |||
| <div className="flex flex-col justify-start text-left gap-8p"> | |||
| <h5 className="subtitle-card-italic-gray">{subtitle}</h5> | |||
| <h3 className="title-card capitalize text-dg-primary-900">{title}</h3> | |||
| <BrakLine className='my-[28px]'/> | |||
| <p className="paragraph">{paragraph}</p> | |||
| </div> | |||
| </div> | |||
| ) | |||
| } | |||
| TimelineCard.propTypes = {}; | |||
| TimelineCard.propTypes = {} | |||
| export default TimelineCard | |||
| export default TimelineCard; | |||
| @@ -1,74 +1,78 @@ | |||
| import React from "react"; | |||
| import React from 'react'; | |||
| import { motion } from "framer-motion"; | |||
| import OrbitOnScroll from "./shared/graphics/OrbitOnScroll"; | |||
| import PageHeading from "./shared/PageHeading"; | |||
| import WhyUsCard from "./WhyUsCard"; | |||
| import { motion } from 'framer-motion'; | |||
| import OrbitOnScroll from './shared/graphics/OrbitOnScroll'; | |||
| import PageHeading from './shared/PageHeading'; | |||
| import WhyUsCard from './WhyUsCard'; | |||
| import why1 from './../assets/icons/why-us-1.svg'; | |||
| import why2 from './../assets/icons/why-us-2.svg'; | |||
| import why3 from './../assets/icons/why-us-3.svg'; | |||
| import why1 from './../assets/icons/why-us-1.svg' | |||
| import why2 from './../assets/icons/why-us-2.svg' | |||
| import why3 from './../assets/icons/why-us-3.svg' | |||
| import Wrapper from '../layout/Wrapper' | |||
| import Wrapper from '../layout/Wrapper'; | |||
| const api_url = process.env.REACT_APP_API_URL; | |||
| const _data = { | |||
| heading: { | |||
| subheading: "Why us", | |||
| heading:"Dedicated and Long-lasting Partnerships", | |||
| paragraph1: 'Committed and loyal we build long-lasting partnerships that go beyond technology. We believe that the key to a prosperous partnership is empathy and understanding.', | |||
| paragraph2: "We collaborate with Fortune 500 companies, innovative start-ups, and established industry leaders. We deliver specialized software solutions and services that enable businesses to expand and face tomorrow's problems by combining world-class engineering teams, sector knowledge, and technical experts.", | |||
| subheading: 'Why us', | |||
| heading: 'Dedicated and Long-lasting Partnerships', | |||
| paragraph1: | |||
| 'Committed and loyal we build long-lasting partnerships that go beyond technology. We believe that the key to a prosperous partnership is empathy and understanding.', | |||
| paragraph2: | |||
| 'We think that our success is directly related to the success of our clients, so we are committed to assisting them in achieving their business goals. After over 15 years of software development, we are convinced that solution is there. With our purpose, everyone at Diligent has a clear and shared understanding of why we do business and what influence we intend to make as a company on business and society.', | |||
| }, | |||
| card_left: { | |||
| imgUrl: why1, | |||
| heading: "Innovative Solutions", | |||
| paragraph: "Technology is just one aspect of our client relationships. Enthusiasts to the core, we bring innovative and real-life solutions to each client’s problems through a deep understanding of their market, approach, and vision.", | |||
| alt: 'Innovative Solutions', | |||
| heading: 'Innovative Solutions', | |||
| paragraph: | |||
| 'Technology is just one aspect of our client relationships. Enthusiasts to the core, we bring innovative and real-life solutions to each client’s problems through a deep understanding of their market, approach, and vision.', | |||
| }, | |||
| card_mid: { | |||
| imgUrl: why2, | |||
| heading: "Product Discovery", | |||
| paragraph: "An idea solves a problem. We help you to create that idea, build a product and scale it to be successful in your business. We develop a roadmap to make sure the development is ready to begin constructing the MVP.", | |||
| alt: 'Product Discovery', | |||
| heading: 'Product Discovery', | |||
| paragraph: | |||
| 'An idea solves a problem. We help you to create that idea, build a product and scale it to be successful in your business. We develop a roadmap to make sure the development is ready to begin constructing the MVP.', | |||
| }, | |||
| card_right: { | |||
| imgUrl: why3, | |||
| heading: "End-user Engagement", | |||
| paragraph: "Our company helps clients to create a successful product. We focus on technical quality to ensure that products are up to standards and meet the needs of users. Innovation is key in developing products that are unique and valuable.", | |||
| } | |||
| } | |||
| const WhySection = ({data}) => { | |||
| alt: 'End-user Engagement', | |||
| heading: 'End-user Engagement', | |||
| paragraph: | |||
| 'Our company helps clients to create a successful product. We focus on technical quality to ensure that products are up to standards and meet the needs of users. Innovation is key in developing products that are unique and valuable.', | |||
| }, | |||
| }; | |||
| return ( | |||
| <Wrapper bg hideOverflow> | |||
| const WhySection = ({ data }) => { | |||
| return ( | |||
| <Wrapper bg hideOverflow> | |||
| <div className="relative"> | |||
| <div className="relative h-[1px] w-full m-auto"> | |||
| <div className="absolute hidden lg:block" id="test" style={{ top: '800px', marginLeft: '-200px' }}> | |||
| <div | |||
| className="absolute hidden lg:block" | |||
| id="test" | |||
| style={{ top: '800px', marginLeft: '-200px' }} | |||
| > | |||
| <OrbitOnScroll /> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <motion.section | |||
| id="why_us" | |||
| className=" flex flex-col items-center relative pt-164p pb-240p" | |||
| > | |||
| <motion.section | |||
| id="why_us" | |||
| className=" flex flex-col items-center relative pt-164p pb-240p" | |||
| > | |||
| <div className="flex flex-col justify-center items-center gap-90p"> | |||
| <div className="max-w-[780px]"> | |||
| <PageHeading | |||
| subheading={_data.heading.subheading} | |||
| heading={_data.heading.heading} | |||
| paragraph1={_data.heading.paragraph1} | |||
| paragraph2={_data.heading.paragraph2} | |||
| /> | |||
| <PageHeading | |||
| subheading={_data.heading.subheading} | |||
| heading={_data.heading.heading} | |||
| paragraph1={_data.heading.paragraph1} | |||
| paragraph2={_data.heading.paragraph2} | |||
| /> | |||
| </div> | |||
| <div className="flex flex-col lg:flex-row gap-32p h-fit sm:px-64p lg:px-0"> | |||
| {/* Card - left */} | |||
| <motion.div | |||
| @@ -77,9 +81,8 @@ const WhySection = ({data}) => { | |||
| transition={{ delay: 0, default: { duration: 0.45 } }} | |||
| > | |||
| <WhyUsCard | |||
| image={ | |||
| _data.card_left.imgUrl | |||
| } | |||
| image={_data.card_left.imgUrl} | |||
| alt={_data.card_left.alt} | |||
| heading={_data.card_left.heading} | |||
| paragraph={_data.card_left.paragraph} | |||
| /> | |||
| @@ -91,9 +94,8 @@ const WhySection = ({data}) => { | |||
| transition={{ delay: 0.27, default: { duration: 0.45 } }} | |||
| > | |||
| <WhyUsCard | |||
| image={ | |||
| _data.card_mid.imgUrl | |||
| } | |||
| image={_data.card_mid.imgUrl} | |||
| alt={_data.card_mid.alt} | |||
| heading={_data.card_mid.heading} | |||
| paragraph={_data.card_mid.paragraph} | |||
| /> | |||
| @@ -105,24 +107,18 @@ const WhySection = ({data}) => { | |||
| transition={{ delay: 0.54, default: { duration: 0.45 } }} | |||
| > | |||
| <WhyUsCard | |||
| image={ | |||
| _data.card_right.imgUrl | |||
| } | |||
| image={_data.card_right.imgUrl} | |||
| alt={_data.card_right.alt} | |||
| heading={_data.card_right.heading} | |||
| paragraph={_data.card_right.paragraph} | |||
| /> | |||
| </motion.div> | |||
| </div> | |||
| </div> | |||
| </motion.section> | |||
| </motion.section> | |||
| </div> | |||
| </Wrapper> | |||
| ) | |||
| } | |||
| </Wrapper> | |||
| ); | |||
| }; | |||
| export default WhySection; | |||
| export default WhySection; | |||
| @@ -5,10 +5,10 @@ export default function WhyUsCard(props) { | |||
| <div className="card-no-hover w-fit h-full flex flex-col text-center justify-between group"> | |||
| <img | |||
| src={props.image} | |||
| alt="Card's Icon" | |||
| alt={props.alt} | |||
| className="ml-auto mr-auto block w-2/5 bg-baby-blue text-dark-gray rounded-full" | |||
| /> | |||
| <h3 className="mt-6 font-semibold text-title">{props.heading}</h3> | |||
| <h4 className="mt-6 font-semibold text-title">{props.heading}</h4> | |||
| <p className="mt-6 text-sm">{props.paragraph}</p> | |||
| </div> | |||
| ); | |||
| @@ -16,6 +16,7 @@ export default function WhyUsCard(props) { | |||
| WhyUsCard.propTypes = { | |||
| image: propTypes.string, | |||
| alt: propTypes.string, | |||
| heading: propTypes.string, | |||
| paragraph: propTypes.string, | |||
| }; | |||
| @@ -0,0 +1,22 @@ | |||
| import React from 'react' | |||
| import {Link} from 'react-router-dom'; | |||
| const CustomLink = ({href, downloadFile, bg, txt, children}) => { | |||
| return ( | |||
| // <a href={href} {...(downloadFile && { download="My_File.pdf" })} (downloadFile download="My_File.pdf")> | |||
| // {context} | |||
| // </a> | |||
| <Link {...{ | |||
| className: 'flex gap-2 items-center px-[16px] py-[12px] text-p font-medium bg-[#8568BF] text-white rounded-full' , | |||
| to: href, | |||
| target: '_blank', | |||
| ...(downloadFile && {download: downloadFile}), | |||
| }}> | |||
| {children} | |||
| </Link> | |||
| ) | |||
| } | |||
| export default CustomLink | |||
| @@ -0,0 +1,9 @@ | |||
| import React from 'react' | |||
| const TertiaryButton = ({action, icon}) => { | |||
| return ( | |||
| <button onClick={() => action()}></button> | |||
| ) | |||
| } | |||
| export default TertiaryButton | |||
| @@ -1,15 +1,15 @@ | |||
| import PropTypes from 'prop-types'; | |||
| import Hex from './../../assets/icons/life/hexLife.svg'; | |||
| export default function CardLife({heading, paragraph, number}) { | |||
| export default function CardLife({ heading, paragraph, number }) { | |||
| return ( | |||
| <div className="relative flex flex-col items-start text-left card-plain w-full"> | |||
| <div className='absolute top-8 left-2 z-10'> | |||
| <img src={Hex} /> | |||
| </div> | |||
| <div className='absolute top-10 left-6 z-20'> | |||
| <p className='paragraph text-white'>{number}.</p> | |||
| </div> | |||
| <div className="absolute top-8 left-2 z-10"> | |||
| <img src={Hex} alt="Purple hex backgorund" /> | |||
| </div> | |||
| <div className="absolute top-10 left-6 z-20"> | |||
| <p className="paragraph text-white">{number}.</p> | |||
| </div> | |||
| <div className="flex flex-row justify-start items-start"> | |||
| <h2 className="text-xl font-semibold dark:text-white ml-2">{heading}</h2> | |||
| </div> | |||
| @@ -22,4 +22,4 @@ CardLife.propTypes = { | |||
| heading: PropTypes.string, | |||
| paragraph: PropTypes.string, | |||
| number: PropTypes.number, | |||
| }; | |||
| }; | |||
| @@ -29,25 +29,34 @@ export default function ClientForm() { | |||
| const validationSchema = Yup.object({ | |||
| subject: Yup.string() | |||
| .min(2, "Subject too short") | |||
| .max(50, "Subject too long") | |||
| .required('Subject is Required'), | |||
| .min(2, 'Subject too short') | |||
| .max(50, 'Subject too long') | |||
| .required('Subject is Required'), | |||
| email: Yup.string().email('Invalid email format').required('Email is Required'), | |||
| firstName: Yup.string().min(2, "First name too short") | |||
| .max(50, "First name too long").required('First Name is Required'), | |||
| lastName: Yup.string().min(2, "Last name too short") | |||
| .max(50, "Last name too long").required('Last Name is Required'), | |||
| description: Yup.string().trim().min(2, "Description too short").required('Description is Required'), | |||
| firstName: Yup.string() | |||
| .min(2, 'First name too short') | |||
| .max(50, 'First name too long') | |||
| .required('First Name is Required'), | |||
| lastName: Yup.string() | |||
| .min(2, 'Last name too short') | |||
| .max(50, 'Last name too long') | |||
| .required('Last Name is Required'), | |||
| description: Yup.string() | |||
| .trim() | |||
| .min(2, 'Description too short') | |||
| .required('Description is Required'), | |||
| }); | |||
| return ( | |||
| <div className="mt-10 sm:mt-0 mx-auto"> | |||
| <div className="md:grid md:grid-cols-2 md:gap-6"> | |||
| <motion.div className="mt-5 md:mt-0 md:col-span-1" | |||
| initial={{ x: -60, opacity: 0 }} | |||
| animate={{ x: 0, opacity: 1 }} | |||
| exit={{ x: -60, opacity: 0 }} | |||
| transition={{ duration: 0.3, ease: 'easeOut' }}> | |||
| <motion.div | |||
| className="mt-5 md:mt-0 md:col-span-1" | |||
| initial={{ x: -60, opacity: 0 }} | |||
| animate={{ x: 0, opacity: 1 }} | |||
| exit={{ x: -60, opacity: 0 }} | |||
| transition={{ duration: 0.3, ease: 'easeOut' }} | |||
| > | |||
| <Formik | |||
| initialValues={clientForm} | |||
| validationSchema={validationSchema} | |||
| @@ -278,12 +287,14 @@ export default function ClientForm() { | |||
| )} | |||
| </Formik> | |||
| </motion.div> | |||
| <motion.div className="mt-5 md:mt-0 md:col-span-1 flex items-center" | |||
| initial={{ x: 60, opacity: 0 }} | |||
| animate={{ x: 0, opacity: 1 }} | |||
| exit={{ x: 60, opacity: 0 }} | |||
| transition={{ duration: 0.3, ease: 'easeOut' }}> | |||
| <img src={img} /> | |||
| <motion.div | |||
| className="mt-5 md:mt-0 md:col-span-1 flex items-center" | |||
| initial={{ x: 60, opacity: 0 }} | |||
| animate={{ x: 0, opacity: 1 }} | |||
| exit={{ x: 60, opacity: 0 }} | |||
| transition={{ duration: 0.3, ease: 'easeOut' }} | |||
| > | |||
| <img src={img} alt="Our Team's image" /> | |||
| </motion.div> | |||
| </div> | |||
| </div> | |||
| @@ -1,5 +1,11 @@ | |||
| import React from 'react' | |||
| import { SliderProvider, SliderTrack, Slide, SliderButton, DotsNav } from '@faceless-ui/slider' | |||
| import React from 'react'; | |||
| import { | |||
| SliderProvider, | |||
| SliderTrack, | |||
| Slide, | |||
| SliderButton, | |||
| DotsNav, | |||
| } from '@faceless-ui/slider'; | |||
| import img1 from './../../../assets/images/Slider/1.png'; | |||
| import img2 from './../../../assets/images/Slider/2.png'; | |||
| import img3 from './../../../assets/images/Slider/3.png'; | |||
| @@ -12,48 +18,36 @@ import img9 from './../../../assets/images/Slider/9.png'; | |||
| import img10 from './../../../assets/images/Slider/10.png'; | |||
| import './index.css'; | |||
| const slides = [ | |||
| img1, img2, img3, img4, img5, img6, img7, img8, img9, img10 | |||
| ] | |||
| const slides = [img1, img2, img3, img4, img5, img6, img7, img8, img9, img10]; | |||
| const FacelessSlider = () => { | |||
| return ( | |||
| <SliderProvider | |||
| slidesToShow={3} | |||
| autoPlay | |||
| scrollSnap | |||
| dragScroll | |||
| > | |||
| <div className={""}> | |||
| {/* <SliderButton direction="prev"> | |||
| <SliderProvider slidesToShow={3} autoPlay scrollSnap dragScroll> | |||
| <div className={''}> | |||
| {/* <SliderButton direction="prev"> | |||
| Previous | |||
| </SliderButton> | |||
| <SliderButton direction="next"> | |||
| Next | |||
| </SliderButton> */} | |||
| </div> | |||
| <div className='rounded-xl overflow-hidden mt-4'> | |||
| <SliderTrack className={" track h-full mt-10 rounded-xl"}> | |||
| {slides.map((slide, index) => ( | |||
| <Slide | |||
| key={index} | |||
| index={index} | |||
| className={"h-full"} | |||
| > | |||
| <img src={slide} className={'w-full'}></img> | |||
| </Slide> | |||
| ))} | |||
| </SliderTrack> | |||
| </div> | |||
| {/* <DotsNav | |||
| </div> | |||
| <div className="rounded-xl overflow-hidden mt-4"> | |||
| <SliderTrack className={' track h-full mt-10 rounded-xl'}> | |||
| {slides.map((slide, index) => ( | |||
| <Slide key={index} index={index} className={'h-full'}> | |||
| <img src={slide} alt="Our Team's image" className={'w-full'}></img> | |||
| </Slide> | |||
| ))} | |||
| </SliderTrack> | |||
| </div> | |||
| {/* <DotsNav | |||
| className={"dots"} | |||
| dotClassName={"dot"} | |||
| activeDotClassName={"dotIsActive"} | |||
| /> */} | |||
| </SliderProvider> | |||
| ) | |||
| } | |||
| </SliderProvider> | |||
| ); | |||
| }; | |||
| export default FacelessSlider; | |||
| @@ -3,7 +3,7 @@ import logo from '../../assets/logos/LogoColumn.svg'; | |||
| import bg_socials from '../../assets/logos/socials_bg.png'; | |||
| import SocialMediaLinks from './SocialMediaLinks'; | |||
| import { Popover } from '@headlessui/react'; | |||
| import { NavLink, useNavigate } from 'react-router-dom'; | |||
| import { NavLink, useLocation, useNavigate } from 'react-router-dom'; | |||
| const footerText = | |||
| 'Custom software solutions for variety of industries with the emphasis on reliability, innovation and top quality.'; | |||
| @@ -11,8 +11,8 @@ const footerText = | |||
| const copyrightText = 'Copyright © 2022. Diligent Software. All rights reserved.'; | |||
| export default function Footer({ links, scrollToView, activeLinks }) { | |||
| const home = useNavigate(); | |||
| const location = useLocation(); | |||
| function handleLogo() { | |||
| home('/'); | |||
| @@ -21,10 +21,8 @@ export default function Footer({ links, scrollToView, activeLinks }) { | |||
| function checkUrl(event) { | |||
| //console.log(location.pathname); | |||
| if (location.pathname === '/') | |||
| scrollToView(event); | |||
| else | |||
| home('/contact'); | |||
| if (location.pathname === '/') scrollToView(event); | |||
| else home('/contact'); | |||
| } | |||
| return ( | |||
| @@ -35,15 +33,20 @@ export default function Footer({ links, scrollToView, activeLinks }) { | |||
| alt="Social Medias Background" | |||
| className="w-2/5 absolute opacity-50" | |||
| /> | |||
| <img src={logo} onClick={handleLogo} className=" w-16 pb-8 cursor-pointer" /> | |||
| <img | |||
| src={logo} | |||
| alt="Diligent logo" | |||
| onClick={handleLogo} | |||
| className=" w-16 pb-8 cursor-pointer" | |||
| /> | |||
| <p className="text-sm text-gray-400 w-4/5 md:w-1/2 lg:w-1/3 text-center pb-8"> | |||
| {footerText} | |||
| </p> | |||
| <Popover.Group as="nav" className="hidden md:flex space-x-10 z-10"> | |||
| {links.map(item => ( | |||
| {links.map((item,index) => ( | |||
| <NavLink | |||
| key={item.name} | |||
| to={item.href} | |||
| key={index} | |||
| to={item.path} | |||
| className={({ isActive }) => { | |||
| return `text-base font-medium hover:text-dg-primary-900 focus:text-dg-primary-900 active:text-dg-primary-900 capitalize ${activeLinks( | |||
| isActive, | |||
| @@ -51,7 +54,7 @@ export default function Footer({ links, scrollToView, activeLinks }) { | |||
| )}`; | |||
| }} | |||
| > | |||
| {item.name} | |||
| {item.title} | |||
| </NavLink> | |||
| ))} | |||
| {/* React Router Link does not support Anchor tags */} | |||
| @@ -63,7 +66,12 @@ export default function Footer({ links, scrollToView, activeLinks }) { | |||
| </div> | |||
| </Popover.Group> | |||
| <SocialMediaLinks divWidth="2/5" iconSize="75" iconSizeHover="95" /> | |||
| <a href="/privacypolicy" className="underline-offset-1 text-xs text-dg-primary-600 text-center cursor-pointer pt-8 z-20">Privacy Policy</a> | |||
| <a | |||
| href="/privacypolicy" | |||
| className="underline-offset-1 text-xs text-dg-primary-600 text-center cursor-pointer pt-8 z-20" | |||
| > | |||
| Privacy Policy | |||
| </a> | |||
| <p className="text-xs text-gray-400 text-center pt-8">{copyrightText}</p> | |||
| </div> | |||
| </div> | |||
| @@ -61,12 +61,18 @@ export default function JobForm(props) { | |||
| const validationSchema = Yup.object({ | |||
| email: Yup.string().email('Invalid email format').required('Email is Required'), | |||
| firstName: Yup.string().min(2, "First name too short") | |||
| .max(50, "First name too long").required('First Name is Required'), | |||
| lastName: Yup.string().min(2, "Last name too short") | |||
| .max(50, "Last name too long").required('Last name is Required'), | |||
| coverLetter: Yup.string().trim().min(2, "Cover Letter too short").required('Cover Letter is Required'), | |||
| firstName: Yup.string() | |||
| .min(2, 'First name too short') | |||
| .max(50, 'First name too long') | |||
| .required('First Name is Required'), | |||
| lastName: Yup.string() | |||
| .min(2, 'Last name too short') | |||
| .max(50, 'Last name too long') | |||
| .required('Last name is Required'), | |||
| coverLetter: Yup.string() | |||
| .trim() | |||
| .min(2, 'Cover Letter too short') | |||
| .required('Cover Letter is Required'), | |||
| }); | |||
| return ( | |||
| @@ -94,9 +100,8 @@ export default function JobForm(props) { | |||
| return null; | |||
| } else { | |||
| const base64 = await convertBase64(file); | |||
| return base64; | |||
| return base64; | |||
| } | |||
| }; | |||
| //convert file | |||
| const convertBase64 = file => { | |||
| @@ -424,9 +429,11 @@ export default function JobForm(props) { | |||
| Submit | |||
| </button> | |||
| </div> | |||
| {sucMsg && <div className={'text-sm text-right text-dg-primary-900'}> | |||
| Submission Succesful! Thank you! | |||
| </div> } | |||
| {sucMsg && ( | |||
| <div className={'text-sm text-right text-dg-primary-900'}> | |||
| Submission Succesful! Thank you! | |||
| </div> | |||
| )} | |||
| </div> | |||
| <div className="col-span-1 sm:col-span-1 lg:col-span-1"></div> | |||
| @@ -444,7 +451,7 @@ export default function JobForm(props) { | |||
| exit={{ x: 60, opacity: 0 }} | |||
| transition={{ duration: 0.3, ease: 'easeOut' }} | |||
| > | |||
| <img src={img} /> | |||
| <img src={img} alt="Our Team's image" /> | |||
| </motion.div> | |||
| </div> | |||
| </div> | |||
| @@ -15,46 +15,51 @@ export default function Navigation({ links, scrollToView, activeLinks }) { | |||
| home('/'); | |||
| } | |||
| function checkUrl(event) { | |||
| //console.log(location.pathname); | |||
| if (location.pathname === '/') | |||
| scrollToView(event); | |||
| else | |||
| home('/contact'); | |||
| } | |||
| // 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 ( | |||
| <Popover className="bg-white dark:bg-dg-primary-1700 fixed w-full top-0 z-50"> | |||
| <Wrapper> | |||
| <div className="flex justify-between items-center border-gray-100 dark:border-dg-primary-1800 py-6 md:space-x-10"> | |||
| <div className="flex justify-start lg:w-0 lg:flex-1"> | |||
| <a href="#"> | |||
| <span className="sr-only">Diligent</span> | |||
| <img className="h-8 w-auto sm:h-10" src={logo} alt="diligent" onClick={()=>handleLogo()} /> | |||
| <img | |||
| className="h-8 w-auto sm:h-10" | |||
| src={logo} | |||
| alt="Diligent logo" | |||
| onClick={() => handleLogo()} | |||
| /> | |||
| </a> | |||
| </div> | |||
| <div className="mr-2 -my-2 md:hidden"> | |||
| <Popover.Button className="bg-white rounded-md p-2 inline-flex items-center justify-center text-dg-primary-900 focus:outline-none"> | |||
| <img src={menuIcon} className='h-[30px]'/> | |||
| <img src={menuIcon} alt="Menu" className="h-[30px]" /> | |||
| {/*<span className="sr-only">Open menu</span> | |||
| <div className="h-6 w-6" aria-hidden="true" />*/} | |||
| </Popover.Button> | |||
| </div> | |||
| <Popover.Group as="nav" className="hidden md:flex space-x-8 lg:space-x-10 items-center"> | |||
| {links.map(item => ( | |||
| <Popover.Group | |||
| as="nav" | |||
| className="hidden md:flex space-x-8 lg:space-x-10 items-center" | |||
| > | |||
| {links.map((item,index) => ( | |||
| <NavLink | |||
| key={item.name} | |||
| to={item.href} | |||
| key={index} | |||
| to={item.path} | |||
| className={({ isActive }) => { | |||
| return `text-base font-medium dark:text-white hover:text-dg-primary-900 focus:text-dg-primary-900 active:text-dg-primary-900 capitalize ${activeLinks( | |||
| 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.name} | |||
| {item.title} | |||
| </NavLink> | |||
| ))} | |||
| {/* React Router Link does not support Anchor tags */} | |||
| @@ -62,7 +67,7 @@ export default function Navigation({ links, scrollToView, activeLinks }) { | |||
| // onClick={event => scrollToView(event)} | |||
| onClick={event => checkUrl(event)} | |||
| href="#contact" | |||
| className="contact-us-link" | |||
| className="contact-us-link text-p" | |||
| > | |||
| Contact | |||
| </div> | |||
| @@ -96,7 +101,12 @@ export default function Navigation({ links, scrollToView, activeLinks }) { | |||
| <div className="pt-5 pb-6 px-5"> | |||
| <div className="flex items-center justify-between"> | |||
| <div> | |||
| <img className="h-8 w-auto cursor-pointer" src={logo} alt="Diligent" onClick={()=>handleLogo()} /> | |||
| <img | |||
| className="h-8 w-auto cursor-pointer" | |||
| src={logo} | |||
| alt="Diligent" | |||
| onClick={() => handleLogo()} | |||
| /> | |||
| </div> | |||
| <div className="-mr-2"> | |||
| <Popover.Button className="bg-white rounded-md p-2 inline-flex items-center justify-center transition-all text-dg-primary-900 hover:text-white hover:transition-all hover:bg-dg-primary-900 focus:outline-none"> | |||
| @@ -108,18 +118,16 @@ export default function Navigation({ links, scrollToView, activeLinks }) { | |||
| </div> | |||
| <div className="mt-6"> | |||
| <nav className="grid gap-y-8"> | |||
| {links.map(item => ( | |||
| {links.map((item,index) => ( | |||
| <NavLink | |||
| onClick={() => close()} | |||
| key={item.name} | |||
| to={item.href} | |||
| className="p-3 flex justify-center items-center rounded-md transition-all hover:transition-all hover:bg-dg-primary-900 hover:text-white" | |||
| 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" | |||
| /> | |||
| <div aria-hidden="true" /> | |||
| <span className="ml-3 text-base font-medium text-inherit"> | |||
| {item.name} | |||
| {item.title} | |||
| </span> | |||
| </NavLink> | |||
| ))} | |||
| @@ -129,9 +137,8 @@ export default function Navigation({ links, scrollToView, activeLinks }) { | |||
| close(); | |||
| checkUrl(event); | |||
| }} | |||
| className="contact-us-link flex justify-center items-center" | |||
| className="contact-us-link flex justify-center items-center text-p" | |||
| > | |||
| <span className="ml-3 text-base font-medium text-inherit"> | |||
| Contact | |||
| </span> | |||
| @@ -3,8 +3,8 @@ import propTypes from 'prop-types'; | |||
| export default function PageHeading(props) { | |||
| return ( | |||
| <div className="flex flex-col gap-8p items-center justify-center"> | |||
| <h6 className="subheading">{props.subheading}</h6> | |||
| <h1 className="heading text-center">{props.heading}</h1> | |||
| <h2 className="subheading">{props.subheading}</h2> | |||
| <h3 className="heading text-center">{props.heading}</h3> | |||
| <div className="flex flex-col gap-16p"> | |||
| <p className="paragraph text-start">{props.paragraph1}</p> | |||
| <p className="paragraph text-start">{props.paragraph2}</p> | |||
| @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' | |||
| 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 ? " title-colored" : "") + (pb && ` pb-2`)}> | |||
| <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> | |||
| <h1 className={"heading" + (left ? " text-left":" text-center")}>{heading}</h1> | |||
| </div> | |||
| @@ -1,22 +1,35 @@ | |||
| import React, { useEffect, useState } from "react"; | |||
| import React, { useEffect, useState } from 'react'; | |||
| const ProcessCard = ({numeric, id, title, subtitle, text}) => { | |||
| const [paragraphs, setParagraphs] = useState([]); | |||
| const left = (id-1) % 2 === 0; | |||
| const ProcessCard = ({ numeric, id, title, subtitle, text }) => { | |||
| const [paragraphs, setParagraphs] = useState([]); | |||
| const left = (id - 1) % 2 === 0; | |||
| useEffect(() => { | |||
| setParagraphs(text); | |||
| },[text]); | |||
| return ( | |||
| <div className={"max-w-[700px] rounded-[32px] card-no-hover relative overflow-hidden" + (left ? " self-start" : " self-end")}> | |||
| {numeric && <div className="absolute top-0 left-0 py-3 px-6 bg-dg-primary-900 text-white leaf">{id}</div>} | |||
| <div className="flex flex-col justify-start text-left gap-8p"> | |||
| <h3 className="title-card">{title}</h3> | |||
| <h5 className="subtitle-card-italic">{subtitle}</h5> | |||
| {paragraphs && paragraphs.map((item, index) => <p className="paragraph" key={index}>{item.paragraph}</p>)} | |||
| </div> | |||
| useEffect(() => { | |||
| setParagraphs(text); | |||
| }, [text]); | |||
| return ( | |||
| <div | |||
| className={ | |||
| 'max-w-[700px] rounded-[32px] card-no-hover relative overflow-hidden' + | |||
| (left ? ' self-start' : ' self-end') | |||
| } | |||
| > | |||
| {numeric && ( | |||
| <div className="absolute top-0 left-0 py-3 px-6 bg-dg-primary-900 text-white leaf"> | |||
| {id} | |||
| </div> | |||
| ) | |||
| } | |||
| )} | |||
| <div className="flex flex-col justify-start text-left gap-8p"> | |||
| <h3 className="title-card">{title}</h3> | |||
| <h4 className="subtitle-card-italic">{subtitle}</h4> | |||
| {paragraphs && | |||
| paragraphs.map((item, index) => ( | |||
| <p className="paragraph" key={index}> | |||
| {item.paragraph} | |||
| </p> | |||
| ))} | |||
| </div> | |||
| </div> | |||
| ); | |||
| }; | |||
| export default ProcessCard; | |||
| @@ -1,66 +1,56 @@ | |||
| import React from 'react' | |||
| import PropTypes from 'prop-types' | |||
| import { Slide, SliderButton, SliderProvider, SliderTrack } from '@faceless-ui/slider' | |||
| import {ReactComponent as CircleArrow } from '../../assets/icons/CircleArrow.svg'; | |||
| import React from 'react'; | |||
| import PropTypes from 'prop-types'; | |||
| import { Slide, SliderButton, SliderProvider, SliderTrack } from '@faceless-ui/slider'; | |||
| import { ReactComponent as CircleArrow } from '../../assets/icons/CircleArrow.svg'; | |||
| import ProcessSvgPart1 from './../../assets/ProcessPart1.svg'; | |||
| import ProcessSvgPart2 from './../../assets/ProcessPart2.svg'; | |||
| import ProcessSvgPart3 from './../../assets/ProcessPart3.svg'; | |||
| const slides = [ | |||
| ProcessSvgPart1, ProcessSvgPart2, ProcessSvgPart3 | |||
| ] | |||
| const slides = [ProcessSvgPart1, ProcessSvgPart2, ProcessSvgPart3]; | |||
| const ProcessFacelessSlider = props => { | |||
| return ( | |||
| <SliderProvider | |||
| slidesToShow={1} | |||
| scrollSnap | |||
| dragScroll | |||
| > | |||
| <div className={""}> | |||
| {/* <SliderButton direction="prev"> | |||
| return ( | |||
| <SliderProvider slidesToShow={1} scrollSnap dragScroll> | |||
| <div className={''}> | |||
| {/* <SliderButton direction="prev"> | |||
| Previous | |||
| </SliderButton> | |||
| <SliderButton direction="next"> | |||
| Next | |||
| </SliderButton> */} | |||
| </div> | |||
| <div className='rounded-xl overflow-hidden mt-4'> | |||
| <SliderTrack className={" track h-full mt-10 rounded-xl"}> | |||
| {slides.map((slide, index) => ( | |||
| <Slide | |||
| key={index} | |||
| index={index} | |||
| className={"h-full"} | |||
| > | |||
| <img src={slide} className={'h-full mx-auto'}></img> | |||
| </Slide> | |||
| ))} | |||
| </SliderTrack> | |||
| </div> | |||
| <div className='flex justify-between w-2/5 mt-8 mx-auto'> | |||
| </div> | |||
| <div className="rounded-xl overflow-hidden mt-4"> | |||
| <SliderTrack className={' track h-full mt-10 rounded-xl'}> | |||
| {slides.map((slide, index) => ( | |||
| <Slide key={index} index={index} className={'h-full'}> | |||
| <img | |||
| src={slide} | |||
| alt={`step ${index + 1}`} | |||
| className={'h-full mx-auto'} | |||
| ></img> | |||
| </Slide> | |||
| ))} | |||
| </SliderTrack> | |||
| </div> | |||
| <div className="flex justify-between w-2/5 mt-8 mx-auto"> | |||
| <SliderButton direction="prev"> | |||
| <CircleArrow /> | |||
| </SliderButton> | |||
| <SliderButton direction="next"> | |||
| <CircleArrow className='rotate-180' /> | |||
| </SliderButton> | |||
| </div> | |||
| {/* <DotsNav | |||
| <CircleArrow /> | |||
| </SliderButton> | |||
| <SliderButton direction="next"> | |||
| <CircleArrow className="rotate-180" /> | |||
| </SliderButton> | |||
| </div> | |||
| {/* <DotsNav | |||
| className={"dots"} | |||
| dotClassName={"dot"} | |||
| activeDotClassName={"dotIsActive"} | |||
| /> */} | |||
| </SliderProvider> | |||
| ) | |||
| } | |||
| </SliderProvider> | |||
| ); | |||
| }; | |||
| ProcessFacelessSlider.propTypes = {} | |||
| ProcessFacelessSlider.propTypes = {}; | |||
| export default ProcessFacelessSlider | |||
| export default ProcessFacelessSlider; | |||
| @@ -55,9 +55,3 @@ export default function SocialMediaLinks(props) { | |||
| </div> | |||
| ); | |||
| } | |||
| SocialMediaLinks.propTypes = { | |||
| divWidth: PropTypes.string, | |||
| iconSize: PropTypes.string, | |||
| iconSizeHover: PropTypes.string, | |||
| }; | |||
| @@ -2,9 +2,9 @@ import React from 'react'; | |||
| const TechNuggets = ({ tech }) => { | |||
| return ( | |||
| <div className="flex gap-2 mt-2"> | |||
| <div className="flex gap-2 mt-2 flex-wrap"> | |||
| {tech.map((item, index) => ( | |||
| <div className="px-4 py-2 text-white text-title-24 font-medium bg-[#9FA2DD] rounded-lg" key={index}>{item}</div> | |||
| <div className="px-4 py-1 text-white text-p whitespace-nowrap font-medium bg-[#9FA2DD] rounded-lg" key={index}>{item}</div> | |||
| ))} | |||
| </div> | |||
| ); | |||
| @@ -1,27 +1,39 @@ | |||
| import React from "react"; | |||
| import { ReactComponent as TestemonialsSVG } from "../../../assets/graphics/TestemonialsSVG.svg"; | |||
| import React from 'react'; | |||
| import { ReactComponent as TestemonialsSVG } from '../../../assets/graphics/TestemonialsSVG.svg'; | |||
| export default function TestimonialCard({ | |||
| paragraph, | |||
| clientName, | |||
| clientRole, | |||
| clientImg, | |||
| imageAlt, | |||
| }) { | |||
| const cardClassList = | |||
| 'px-12 py-12 bg-white dark:bg-dg-primary-1700 text-dark-gray dark:text-white shadow-md dark:border-dg-primary-1500 dark:border-solid dark:border text-center rounded-xl'; | |||
| export default function TestimonialCard({paragraph, clientName, clientRole, clientImg}) { | |||
| const cardClassList = 'px-12 py-12 bg-white dark:bg-dg-primary-1700 text-dark-gray dark:text-white shadow-md dark:border-dg-primary-1500 dark:border-solid dark:border text-center rounded-xl'; | |||
| return ( | |||
| <div className="relative h-fit md:mr-90p"> | |||
| <div className="absolute z-20 -bottom-[120px] -right-[90px] hidden md:block"> | |||
| <TestemonialsSVG /> | |||
| <div className="absolute top-0 bottom-0 left-0 right-0 flex justify-center items-center"> | |||
| <img src={clientImg} className='mx-auto' style={{margin: '2px 2px 40px 20px', height:64, width:64, borderRadius:'50%'}}/> | |||
| </div> | |||
| </div> | |||
| <div className={cardClassList + ' flex flex-col justify-between max-w-[460px]'}> | |||
| <p className="text-p-italic italic text-gray-500">"{paragraph}"</p> | |||
| <h4 className="text-dg-primary-900">{clientName}</h4> | |||
| <p>{clientRole}</p> | |||
| </div> | |||
| return ( | |||
| <div className="relative h-fit md:mr-90p"> | |||
| <div className="absolute z-20 -bottom-[120px] -right-[90px] hidden md:block"> | |||
| <TestemonialsSVG /> | |||
| <div className="absolute top-0 bottom-0 left-0 right-0 flex justify-center items-center"> | |||
| <img | |||
| src={clientImg} | |||
| alt={imageAlt} | |||
| className="mx-auto" | |||
| style={{ | |||
| margin: '2px 2px 40px 20px', | |||
| height: 64, | |||
| width: 64, | |||
| borderRadius: '50%', | |||
| }} | |||
| /> | |||
| </div> | |||
| ) | |||
| } | |||
| </div> | |||
| <div className={cardClassList + ' flex flex-col justify-between max-w-[460px]'}> | |||
| <p className="text-p-italic italic text-gray-500">"{paragraph}"</p> | |||
| <h4 className="text-dg-primary-900">{clientName}</h4> | |||
| <p>{clientRole}</p> | |||
| </div> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| import React, { useEffect } from "react"; | |||
| import { useLocation } from "react-router-dom"; | |||
| 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]); | |||
| } | |||
| export default useAnalytics; | |||
| @@ -3,7 +3,6 @@ import React, {useState, useEffect} from "react"; | |||
| const useWindowSize = () => { | |||
| // Initialize state with undefined width/height so server and client renders match | |||
| // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/ | |||
| const [windowSize, setWindowSize] = useState({ | |||
| width: undefined, | |||
| height: undefined, | |||
| @@ -5,7 +5,6 @@ import App from './App'; | |||
| import reportWebVitals from './reportWebVitals'; | |||
| import { BrowserRouter } from 'react-router-dom'; | |||
| import ScrollToTop from './components/root/ScrollToTop'; | |||
| if (module.hot) module.hot.accept() | |||
| @@ -13,7 +12,6 @@ if (module.hot) module.hot.accept() | |||
| ReactDOM.render( | |||
| <React.StrictMode> | |||
| <BrowserRouter> | |||
| {/* <ScrollToTop /> */} | |||
| <App /> | |||
| </BrowserRouter> | |||
| </React.StrictMode>, | |||
| @@ -14,7 +14,7 @@ import Ideas from './../assets/icons/values/ideas.svg'; | |||
| import NisExpress from '../assets/NE_large_logo.png'; | |||
| import Djole from './../' | |||
| import Djole from './../'; | |||
| import valuesBG from './../assets/ValuesBG.svg'; | |||
| import TimelineCardsWrapper from '../components/TimelineWrapper'; | |||
| import TimelineCard from '../components/TimelineCard'; | |||
| @@ -23,193 +23,211 @@ 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'; | |||
| const _data = { | |||
| heading: { | |||
| subheading: "About Us", | |||
| heading: "Who We Are", | |||
| imgUrl: 'https://lh6.googleusercontent.com/nCX_ne2JiqAAQqxF2ObEIA6EmP_cl6BciWQUqGaIzrgvv83Eo4nhzcqyZw_pYNxnByo=w2400', | |||
| paragraph: "When ten enthusiasts came together in 2020 with the same vision and impactful goals our journey officially began. We believed that taking small steps could result in meaningful changes and help us succeed in areas of a global pandemic and rapid social changes." | |||
| subheading: 'About Us', | |||
| heading: 'Who We Are', | |||
| imgUrl: | |||
| 'https://lh4.googleusercontent.com/4AxnSLGq46gLcFyYdz1508l45FIeIhlsrb02v-AnNenATYLG15qFgIl3pbBfjHVg1nY=w2400', | |||
| paragraph: | |||
| 'When ten enthusiasts came together in 2020 with the same vision and impactful goals our journey officially began. We believed that taking small steps could result in meaningful changes and help us succeed in areas of a global pandemic and rapid social changes.', | |||
| }, | |||
| segment1: { | |||
| paragraph: "Diligent Software is a collaborative software development team that delivers high-quality custom software solutions while also cultivating a work environment that promotes community, family, learning, and mentoring.", | |||
| imgUrl: "https://lh5.googleusercontent.com/YD0JCH9v2hZ2_M42T7QD4U1CbTPolaelasj0SJF8kDQQiuRFmO9lLukjxfBqg5dxHsY=w2400", | |||
| paragraph: | |||
| 'Diligent Software is a collaborative software development team that delivers high-quality custom software solutions while also cultivating a work environment that promotes community, family, learning, and mentoring.', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/YD0JCH9v2hZ2_M42T7QD4U1CbTPolaelasj0SJF8kDQQiuRFmO9lLukjxfBqg5dxHsY=w2400', | |||
| }, | |||
| segment2: { | |||
| paragraph: "By utilizing cutting-edge technologies, our agile, multi-disciplinary teams provide a combination of product & technology strategies, intelligent experiences, and world-class engineering to help our clients become more engaging, responsive, and efficient.", | |||
| imgUrl: "https://lh6.googleusercontent.com/WEoQNbjwT9EpeG2kM4pvdeJM4MwFoEnSj2Dn0e3vPM54iN6P911_Y0wAXvSsbspd3Lg=w2400", | |||
| paragraph: | |||
| 'By utilizing cutting-edge technologies, our agile, multi-disciplinary teams provide a combination of product & technology strategies, intelligent experiences, and world-class engineering to help our clients become more engaging, responsive, and efficient.', | |||
| imgUrl: | |||
| 'https://lh6.googleusercontent.com/WEoQNbjwT9EpeG2kM4pvdeJM4MwFoEnSj2Dn0e3vPM54iN6P911_Y0wAXvSsbspd3Lg=w2400', | |||
| }, | |||
| subtitle: "Diligent has close to 100 employees located throughout Serbia.", | |||
| subtitleImgUrl: "https://lh5.googleusercontent.com/Nk7pWU1H028YvdMkXvH6CECmQVWtTuKpKQuTUTKzUVXfhCF1JAjXThy1585YnXYdWio=w2400", | |||
| italicParagraph: "We understand that investing in long-term customer relationships is essential, but we also recognize the importance of providing rewarding and challenging careers for our employees.", | |||
| subtitle: 'Diligent has close to 100 employees located throughout Serbia.', | |||
| subtitleImgUrl: | |||
| 'https://lh5.googleusercontent.com/Nk7pWU1H028YvdMkXvH6CECmQVWtTuKpKQuTUTKzUVXfhCF1JAjXThy1585YnXYdWio=w2400', | |||
| italicParagraph: | |||
| 'We understand that investing in long-term customer relationships is essential, but we also recognize the importance of providing rewarding and challenging careers for our employees.', | |||
| segment3: { | |||
| mission: { | |||
| title: "Our Vision", | |||
| imgUrl:"https://lh5.googleusercontent.com/IdGSbzSZ8fRwwkP43Lkzm3fQBRGqywFNpfi2Qe2bkstNXunQGM1zVFrdX4blaiSGuEM=w2400", | |||
| title: 'Our Vision', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/IdGSbzSZ8fRwwkP43Lkzm3fQBRGqywFNpfi2Qe2bkstNXunQGM1zVFrdX4blaiSGuEM=w2400', | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "Our vision is to be a leading software solutions company for a variety of industries. We believe that our growth is directly related to the success of our customers, so we are dedicated to helping them achieve their business goals. " | |||
| paragraph: | |||
| 'Our vision is to be a leading software solutions company for a variety of industries. We believe that our growth is directly related to the success of our customers, so we are dedicated to helping them achieve their business goals. ', | |||
| }, | |||
| { | |||
| paragraph: "We want to be known as a reliable, innovative, and top-quality software service provider in the IT industry. We are constantly striving to exceed the expectations of our customers and to be the best in our field. " | |||
| } | |||
| paragraph: | |||
| 'We want to be known as a reliable, innovative, and top-quality software service provider in the IT industry. We are constantly striving to exceed the expectations of our customers and to be the best in our field. ', | |||
| }, | |||
| ], | |||
| }, | |||
| vision: { | |||
| title: "Our Mission", | |||
| imgUrl: "https://lh3.googleusercontent.com/gqO6y406jsrU5mt2c2rcbZS-2Z6Q9rg2zxHQ576LExMo1ptRx-SVZj2iAkR1wg2lNF0=w2400", | |||
| title: 'Our Mission', | |||
| imgUrl: | |||
| 'https://lh3.googleusercontent.com/gqO6y406jsrU5mt2c2rcbZS-2Z6Q9rg2zxHQ576LExMo1ptRx-SVZj2iAkR1wg2lNF0=w2400', | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "Our mission is to help our customers grow their businesses through creative design and development solutions. We strive to deliver market-defining high-quality solutions that create value and competitive advantage for our customers around the world." | |||
| paragraph: | |||
| 'Our mission is to help our customers grow their businesses through creative design and development solutions. We strive to deliver market-defining high-quality solutions that create value and competitive advantage for our customers around the world.', | |||
| }, | |||
| { | |||
| paragraph: "We are dedicated to providing our clients with the best possible service and continually improving our processes and capabilities to better meet their needs. " | |||
| } | |||
| paragraph: | |||
| 'We are dedicated to providing our clients with the best possible service and continually improving our processes and capabilities to better meet their needs. ', | |||
| }, | |||
| ], | |||
| } | |||
| }, | |||
| }, | |||
| values: { | |||
| heading: "Values", | |||
| cards: [ | |||
| heading: 'Values', | |||
| cards: [ | |||
| { | |||
| id:0, | |||
| id: 0, | |||
| iconUrl: Care, | |||
| title:"Care", | |||
| paragraph: "We believe that by working together and being kind to one another, we can make a difference. We care about work colleagues, ourselves, partnerships, but also the planet. We constantly strive to be helpful, kind, and inclusive in everything we do and looking for ways to be more sustainable. " | |||
| title: 'Care', | |||
| paragraph: | |||
| 'We believe that by working together and being kind to one another, we can make a difference. We care about work colleagues, ourselves, partnerships, but also the planet. We constantly strive to be helpful, kind, and inclusive in everything we do and looking for ways to be more sustainable. ', | |||
| }, | |||
| { | |||
| id:1, | |||
| id: 1, | |||
| iconUrl: Culture, | |||
| title:"Culture", | |||
| paragraph: "Our people love what they do. We provide a fun and supportive environment that empowers our staff to grow, learn, and thrive. We are consistent and transparent in our actions and committed to our clients and colleagues. We believe that together we can achieve more." | |||
| title: 'Culture', | |||
| paragraph: | |||
| 'Our people love what they do. We provide a fun and supportive environment that empowers our staff to grow, learn, and thrive. We are consistent and transparent in our actions and committed to our clients and colleagues. We believe that together we can achieve more.', | |||
| }, | |||
| { | |||
| id:2, | |||
| id: 2, | |||
| iconUrl: Doing, | |||
| title:"Learn by Doing", | |||
| paragraph: "Our legacy is our impact on the people around us. By being kind and helping others, we can make a positive difference and leave a lasting impression. We grow as individuals, as well as we grow as a team." | |||
| title: 'Learn by Doing', | |||
| paragraph: | |||
| 'Our legacy is our impact on the people around us. By being kind and helping others, we can make a positive difference and leave a lasting impression. We grow as individuals, as well as we grow as a team.', | |||
| }, | |||
| { | |||
| id:3, | |||
| id: 3, | |||
| iconUrl: Ideas, | |||
| title:"Ideas Over Hierarchy", | |||
| paragraph: "We believe that the best ideas can come from anywhere, both inside and outside our company. Our job is to seek out those ideas, shape and improve them through candid debate, and take them from concept to action." | |||
| } | |||
| title: 'Ideas Over Hierarchy', | |||
| paragraph: | |||
| 'We believe that the best ideas can come from anywhere, both inside and outside our company. Our job is to seek out those ideas, shape and improve them through candid debate, and take them from concept to action.', | |||
| }, | |||
| ], | |||
| }, | |||
| partners: { | |||
| title: "Partners", | |||
| paragraph: "We collaborate with Fortune 500 companies, innovative start-ups, and established industry leaders. We deliver specialized software solutions and services that enable businesses to expand and face tomorrow's problems by combining world-class engineering teams, sector knowledge, and technical experts.", | |||
| title: 'Partners', | |||
| paragraph: | |||
| "We collaborate with Fortune 500 companies, innovative start-ups, and established industry leaders. We deliver specialized software solutions and services that enable businesses to expand and face tomorrow's problems by combining world-class engineering teams, sector knowledge, and technical experts.", | |||
| icons: [ | |||
| "https://lh4.googleusercontent.com/e5Zf5H4bL-6N4R7TOJIlB7hAPzzIk41dnWlCvJDZKAWyyjbJ_kWmONzHqddi11rb_SA=w2400", | |||
| "https://lh6.googleusercontent.com/4QxTBdL0JdRHjbujuHSEO9ysyQL7N64bykQm4DutzoAB0MOIYBODgShJ9uSChiI1kHo=w2400", | |||
| 'https://lh4.googleusercontent.com/e5Zf5H4bL-6N4R7TOJIlB7hAPzzIk41dnWlCvJDZKAWyyjbJ_kWmONzHqddi11rb_SA=w2400', | |||
| 'https://lh6.googleusercontent.com/4QxTBdL0JdRHjbujuHSEO9ysyQL7N64bykQm4DutzoAB0MOIYBODgShJ9uSChiI1kHo=w2400', | |||
| NisExpress, | |||
| "https://lh6.googleusercontent.com/8TrErMJ6QyxdwhmM57Oiy-41Db7thyvaHmGfb4teaFiYKWFVDd3reL1Ok1T88nAgvaE=w2400", | |||
| "https://lh4.googleusercontent.com/D05_HBhHcJf8Rpbxf7Uc4ix_J4advqIFM6Rwe-Vd9huTQCt2JKocAKqAf_AwszThr2Y=w2400", | |||
| ] | |||
| 'https://lh6.googleusercontent.com/8TrErMJ6QyxdwhmM57Oiy-41Db7thyvaHmGfb4teaFiYKWFVDd3reL1Ok1T88nAgvaE=w2400', | |||
| 'https://lh4.googleusercontent.com/D05_HBhHcJf8Rpbxf7Uc4ix_J4advqIFM6Rwe-Vd9huTQCt2JKocAKqAf_AwszThr2Y=w2400', | |||
| ], | |||
| }, | |||
| industries: { | |||
| title:"Industries", | |||
| title: 'Industries', | |||
| industries: [ | |||
| { | |||
| title: "Fintech", | |||
| paragraph: "We help fintech startups and financial institutions to manage risk and stay ahead of the curve by developing financial software solutions and integrating them with third-party systems while ensuring the stable operation of financial systems.", | |||
| imgUrl: 'https://lh6.googleusercontent.com/hNzi8UOWwAYzL9ZFR5bPnhge1RCIPgaFDwvZ-Cz7jaIRzKOySxZi2duV5-plTpGczLE=w2400', | |||
| }, | |||
| { | |||
| title: "Healthcare", | |||
| paragraph: "We provide the healthcare sector with seamless transitions from an offline business to a tailored digital platform. All with the assistance of cutting-edge technology to enhance the user experience and improve health care delivery.", | |||
| imgUrl: 'https://lh4.googleusercontent.com/8xQPhJ2FZrTFamSUf2EkpL_vsvjAFymUEEX4PWF-R4Mhznt6vo2kkYCHY4gZCF5XjYs=w2400', | |||
| }, | |||
| ], | |||
| { | |||
| title: 'Fintech', | |||
| paragraph: | |||
| 'We help fintech startups and financial institutions to manage risk and stay ahead of the curve by developing financial software solutions and integrating them with third-party systems while ensuring the stable operation of financial systems.', | |||
| imgUrl: | |||
| 'https://lh6.googleusercontent.com/hNzi8UOWwAYzL9ZFR5bPnhge1RCIPgaFDwvZ-Cz7jaIRzKOySxZi2duV5-plTpGczLE=w2400', | |||
| }, | |||
| { | |||
| title: 'Healthcare', | |||
| paragraph: | |||
| 'We provide the healthcare sector with seamless transitions from an offline business to a tailored digital platform. All with the assistance of cutting-edge technology to enhance the user experience and improve health care delivery.', | |||
| imgUrl: | |||
| 'https://lh4.googleusercontent.com/8xQPhJ2FZrTFamSUf2EkpL_vsvjAFymUEEX4PWF-R4Mhznt6vo2kkYCHY4gZCF5XjYs=w2400', | |||
| }, | |||
| ], | |||
| }, | |||
| timeline: { | |||
| subtitle: "our journey", | |||
| title: "Timeline of Our Growth", | |||
| subtitle: 'our journey', | |||
| title: 'Timeline of Our Growth', | |||
| cards: [ | |||
| { | |||
| subtitle: "1st Step", | |||
| title: "First Year of Our Work", | |||
| paragraph: "Our journey began two years ago when a group of ten tech enthusiasts made the decision to put their ideas into practice and accomplish their goals. With more than ten years of technology experience in a variety of industries, including fintech, transportation, and healthcare, they created a modern company that can deliver solutions tailored to each client. " | |||
| subtitle: '1st Step', | |||
| title: 'First Year of Our Work', | |||
| paragraph: | |||
| 'Our journey began two years ago when a group of ten tech enthusiasts made the decision to put their ideas into practice and accomplish their goals. With more than ten years of technology experience in a variety of industries, including fintech, transportation, and healthcare, they created a modern company that can deliver solutions tailored to each client. ', | |||
| }, | |||
| { | |||
| subtitle: "2nd Step", | |||
| title: "Choosing our clients", | |||
| paragraph: "We strive to build strong partnerships with our clients. We can proudly say that our biggest value is a long-lasting partnership with our very first clients. Good impressions and commitment lead us to the first clients. Furthermore, we continue to build long-term partnerships. " | |||
| subtitle: '2nd Step', | |||
| title: 'Choosing our clients', | |||
| paragraph: | |||
| 'We strive to build strong partnerships with our clients. We can proudly say that our biggest value is a long-lasting partnership with our very first clients. Good impressions and commitment lead us to the first clients. Furthermore, we continue to build long-term partnerships. ', | |||
| }, | |||
| { | |||
| subtitle: "3rd Step", | |||
| title: "Overcoming hard times", | |||
| paragraph: "As the COVID-19 pandemic was taking off, we were extremely impressed by how well our team adapted to the changing circumstances. Diligent’s greatest strengths have always been our team of highly qualified and experienced professionals. Diligent team increased from 35 employees to 67 technology experts." | |||
| subtitle: '3rd Step', | |||
| title: 'Overcoming hard times', | |||
| paragraph: | |||
| 'As the COVID-19 pandemic was taking off, we were extremely impressed by how well our team adapted to the changing circumstances. Diligent’s greatest strengths have always been our team of highly qualified and experienced professionals. Diligent team increased from 35 employees to 67 technology experts.', | |||
| }, | |||
| { | |||
| subtitle: "4th Step", | |||
| title: "Where We Are Today", | |||
| paragraph: "We are constantly growing, coding the vision of the future! Today we are about to have 100 employees who diligently work on more than 50 projects, trying to give cutting-edge solutions to the most common and modern problems. Our partnerships with the clients are based on trust and commitment." | |||
| subtitle: '4th Step', | |||
| title: 'Where We Are Today', | |||
| paragraph: | |||
| 'We are constantly growing, coding the vision of the future! Today we are about to have 100 employees who diligently work on more than 50 projects, trying to give cutting-edge solutions to the most common and modern problems. Our partnerships with the clients are based on trust and commitment.', | |||
| }, | |||
| { | |||
| subtitle: "5th Step", | |||
| title: "road to future success", | |||
| paragraph: "Professional and personal growth and development of our employees are crucial for strengthening our team. We strive hard to offer high-quality education, mentoring, and an inspiring environment where everyone may reach their full potential. This will enable us to progress as a team and achieve our long-term goals." | |||
| } | |||
| ] | |||
| } | |||
| } | |||
| subtitle: '5th Step', | |||
| title: 'road to future success', | |||
| paragraph: | |||
| 'Professional and personal growth and development of our employees are crucial for strengthening our team. We strive hard to offer high-quality education, mentoring, and an inspiring environment where everyone may reach their full potential. This will enable us to progress as a team and achieve our long-term goals.', | |||
| }, | |||
| ], | |||
| }, | |||
| }; | |||
| export default function About() { | |||
| useEffect(() => { | |||
| document.title = 'About Us'; | |||
| },[]); | |||
| }, []); | |||
| //useAnalytics(); | |||
| return ( | |||
| <PageLayout> | |||
| <div className="bg-white dark:bg-dg-primary-1700 w-full pt-32"> | |||
| {/* Heading Section */} | |||
| <section | |||
| id="heading" | |||
| className="flex flex-col items-center justify-center max-w-custom m-auto" | |||
| > | |||
| <div className="mb-8 flex flex-col md:flex-row justify-start items-start w-full px-8 xl:px-0"> | |||
| id="heading" | |||
| className="flex flex-col items-center justify-center max-w-custom m-auto" | |||
| > | |||
| <div className="mb-8 flex flex-col md:flex-row gap-4 lg-gap-0 justify-start items-start w-full px-8 xl:px-0"> | |||
| <div className="w-full md:w-1/2 md:pr-16"> | |||
| <h6 className="subheading"> | |||
| {_data.heading.subheading} | |||
| </h6> | |||
| <h1 className="heading text-dg-secondary mt-2"> | |||
| {_data.heading.heading} | |||
| </h1> | |||
| <p className="paragraph mt-4"> | |||
| {_data.heading.paragraph} | |||
| </p> | |||
| <h6 className="subheading">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| <img | |||
| src={_data.heading.imgUrl} | |||
| alt="Our Team's image" | |||
| className="w-full md:w-1/2 text-center" | |||
| /> | |||
| src={_data.heading.imgUrl} | |||
| alt="Our Team's image" | |||
| className="w-full md:w-1/2 text-center -ml-2 lg-ml-0" | |||
| /> | |||
| </div> | |||
| </section> | |||
| {/* The After Heading pt.1 Section */} | |||
| <section | |||
| id="after_heading" | |||
| className="bg-white dark:bg-dg-primary-1700 flex items-center justify-center px-2" | |||
| > | |||
| id="after_heading" | |||
| className="bg-white dark:bg-dg-primary-1700 flex items-center justify-center px-2" | |||
| > | |||
| <div className="my-8 flex flex-col-reverse md:flex-row justify-center items-center max-w-custom m-auto w-full px-8 xl:px-0"> | |||
| <img | |||
| src={_data.segment1.imgUrl} | |||
| alt="Our Team's image" | |||
| className="w-full md:w-1/2 text-center mt-8 md:mt-0" | |||
| /> | |||
| src={_data.segment1.imgUrl} | |||
| alt="Our Team's image" | |||
| className="w-full md:w-1/2 text-center mt-8 md:mt-0" | |||
| /> | |||
| <div className="w-full md:w-1/2 md:pl-16"> | |||
| <p className="paragraph mt-4"> | |||
| {_data.segment1.paragraph} | |||
| </p> | |||
| <p className="paragraph mt-4">{_data.segment1.paragraph}</p> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| @@ -218,20 +236,21 @@ export default function About() { | |||
| <section id="after_heading" className="flex flex-col items-center justify-center"> | |||
| <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"> | |||
| <p className="paragraph mt-4"> | |||
| {_data.segment2.paragraph} | |||
| </p> | |||
| <p className="paragraph mt-4">{_data.segment2.paragraph}</p> | |||
| </div> | |||
| <img | |||
| src={_data.segment2.imgUrl} | |||
| alt="Office's image" | |||
| className="w-full md:w-1/2 text-center" | |||
| /> | |||
| src={_data.segment2.imgUrl} | |||
| alt="Office's image" | |||
| className="w-full md:w-1/2 text-center" | |||
| /> | |||
| </div> | |||
| </section> | |||
| {/* Highlighted Text Section */} | |||
| <section id="highlight" className="flex flex-col items-center justify-center mt-16"> | |||
| <section | |||
| id="highlight" | |||
| className="flex flex-col items-center justify-center mt-16" | |||
| > | |||
| <HighlighedText text={_data.subtitle} /> | |||
| </section> | |||
| @@ -239,10 +258,10 @@ export default function About() { | |||
| <section id="info" className="flex flex-col items-center justify-center mt-16"> | |||
| <div className="flex flex-col items-center justify-center w-full"> | |||
| <img | |||
| src={_data.subtitleImgUrl} | |||
| alt="Info image" | |||
| className="max-w-[660px] w-full" | |||
| /> | |||
| src={_data.subtitleImgUrl} | |||
| alt="Info image" | |||
| className="max-w-[660px] w-full" | |||
| /> | |||
| <p className="text-sm font-medium italic text-gray-500 dark:text-white w-2/3 lg:w-1/3 mt-4"> | |||
| {_data.italicParagraph} | |||
| </p> | |||
| @@ -251,149 +270,139 @@ export default function About() { | |||
| {/* Our Mission & Our Vision Section */} | |||
| <section | |||
| id="mission_vision" | |||
| className="bg-baby-blue dark:bg-dg-primary-1600 flex flex-col items-center justify-center mt-16" | |||
| > | |||
| id="mission_vision" | |||
| className="bg-baby-blue dark:bg-dg-primary-1600 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"> | |||
| <h1 className="heading text-dg-secondary">{_data.segment3.vision.title}</h1> | |||
| {_data.segment3.vision.paragraphs.map((item,index) => ( | |||
| <h2 className="heading text-dg-secondary">{_data.segment3.vision.title}</h2> | |||
| {_data.segment3.vision.paragraphs.map((item, index) => ( | |||
| <p key={index} className="paragraph mt-4"> | |||
| {item.paragraph} | |||
| </p> | |||
| ) | |||
| )} | |||
| ))} | |||
| </div> | |||
| <img | |||
| src={_data.segment3.mission.imgUrl} | |||
| alt="Our mission image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| src={_data.segment3.mission.imgUrl} | |||
| alt="Our mission image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| </div> | |||
| <div className="my-8 flex flex-col-reverse md:flex-row justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0"> | |||
| <img | |||
| src={_data.segment3.vision.imgUrl} | |||
| alt="Our vision image" | |||
| className="text-center w-full md:w-1/2 mt-8 md:mt-0" | |||
| /> | |||
| src={_data.segment3.vision.imgUrl} | |||
| alt="Our vision image" | |||
| className="text-center w-full md:w-1/2 mt-8 md:mt-0" | |||
| /> | |||
| <div className="w-full md:w-1/2 md:pl-16"> | |||
| <h1 className="heading text-dg-secondary">{_data.segment3.mission.title}</h1> | |||
| {_data.segment3.mission.paragraphs.map((item,index) => ( | |||
| <h2 className="heading text-dg-secondary"> | |||
| {_data.segment3.mission.title} | |||
| </h2> | |||
| {_data.segment3.mission.paragraphs.map((item, index) => ( | |||
| <p key={index} className="paragraph mt-4"> | |||
| {item.paragraph} | |||
| </p> | |||
| ) | |||
| )} | |||
| ))} | |||
| </div> | |||
| </div> | |||
| </section> | |||
| {/* Values Section */} | |||
| <section | |||
| id="values" | |||
| className="bg-white dark:bg-dg-primary-1700 flex flex-row items-center justify-center mt-16" | |||
| > | |||
| id="values" | |||
| className="bg-white dark:bg-dg-primary-1700 flex flex-row items-center justify-center mt-16" | |||
| > | |||
| <div className="my-8 flex flex-col justify-center items-start w-full max-w-custom m-auto px-8 xl:px-0"> | |||
| <h1 className="heading text-dg-secondary">{_data.values.heading}</h1> | |||
| <h2 className="heading text-dg-secondary">{_data.values.heading}</h2> | |||
| <div className="absolute justify-center md:flex hidden self-center"> | |||
| <img src={valuesBG}/> | |||
| <img src={valuesBG} alt="Values background" /> | |||
| </div> | |||
| <div className="grid grid-cols-1 md:grid-cols-2 gap-16 w-full mt-8"> | |||
| {_data.values.cards.map((item,index) => ( | |||
| {_data.values.cards.map((item, index) => ( | |||
| <CardValues | |||
| key={index} | |||
| image={item.iconUrl} | |||
| heading={item.title} | |||
| paragraph={item.paragraph} | |||
| /> | |||
| ))} | |||
| key={index} | |||
| image={item.iconUrl} | |||
| heading={item.title} | |||
| paragraph={item.paragraph} | |||
| /> | |||
| ))} | |||
| </div> | |||
| </div> | |||
| </section> | |||
| {/* Partners Section */} | |||
| <section | |||
| id="partners" | |||
| className="bg-baby-blue dark:bg-dg-primary-1600 flex flex-col items-center justify-center mt-16" | |||
| > | |||
| id="partners" | |||
| className="bg-baby-blue dark:bg-dg-primary-1600 flex flex-col items-center justify-center mt-16" | |||
| > | |||
| <div className="my-16 flex flex-col justify-center items-center w-full max-w-custom m-auto px-8 xl:px-0"> | |||
| <div className="w-full md:w-2/3"> | |||
| <h1 className="text-center heading text-dg-secondary"> | |||
| <h2 className="text-center heading text-dg-secondary"> | |||
| {_data.partners.title} | |||
| </h1> | |||
| <p className="text-left paragraph mt-4"> | |||
| {_data.partners.paragraph} | |||
| </p> | |||
| </h2> | |||
| <p className="text-left paragraph mt-4">{_data.partners.paragraph}</p> | |||
| </div> | |||
| <div className="flex flex-row justify-between items-center w-full mt-16"> | |||
| {_data.partners.icons.map((item,index) => ( | |||
| {_data.partners.icons.map((item, index) => ( | |||
| <img | |||
| key={index} | |||
| src={item} | |||
| alt="Partner's image" | |||
| className="w-16 md:w-20 lg:w-24" | |||
| /> | |||
| ))} | |||
| key={index} | |||
| src={item} | |||
| alt="Partner's image" | |||
| className="w-16 md:w-20 lg:w-24" | |||
| /> | |||
| ))} | |||
| </div> | |||
| </div> | |||
| </section> | |||
| {/* Industries Section */} | |||
| <section | |||
| id="industries" | |||
| className="bg-white dark:bg-dg-primary-1700 flex flex-col items-center justify-center mt-16" | |||
| > | |||
| id="industries" | |||
| className="bg-white dark:bg-dg-primary-1700 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"> | |||
| <h1 className="heading text-dg-secondary">{_data.industries.title}</h1> | |||
| <h2 className="heading text-dg-secondary">{_data.industries.title}</h2> | |||
| </div> | |||
| <div className="grid grid-cols-1 lg:grid-cols-2 gap-32 w-full mt-8"> | |||
| {_data.industries.industries.map((industry,index) => ( | |||
| {_data.industries.industries.map((industry, index) => ( | |||
| <div key={index}> | |||
| <h3 className="h3-heading"> | |||
| {industry.title} | |||
| </h3> | |||
| <p className="paragraph mt-2"> | |||
| {industry.paragraph} | |||
| </p> | |||
| <img | |||
| src={industry.imgUrl} | |||
| alt="Industries images" | |||
| className="m-auto" | |||
| /> | |||
| <h3 className="h3-heading">{industry.title}</h3> | |||
| <p className="paragraph mt-2">{industry.paragraph}</p> | |||
| <img src={industry.imgUrl} alt="Industries images" className="m-auto" /> | |||
| </div> | |||
| ))} | |||
| ))} | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <Wrapper bg padding={' py-90p'}> | |||
| <PageTitle heading={_data.timeline.title} subheading={_data.timeline.subtitle} left /> | |||
| <PageTitle | |||
| heading={_data.timeline.title} | |||
| subheading={_data.timeline.subtitle} | |||
| left | |||
| /> | |||
| <div className="my-90p"> | |||
| <div className="w-full relative "> | |||
| <div className="md:absolute top-[5%] left-0 w-full h-full hidden md:block"> | |||
| <TimelineLogo/> | |||
| <TimelineLogo /> | |||
| </div> | |||
| <TimelineCardsWrapper2> | |||
| {_data.timeline.cards.map((item, index) => ( | |||
| <TimelineCard | |||
| key={index} | |||
| id={index} | |||
| title={item.title} | |||
| subtitle={item.subtitle} | |||
| paragraph={item.paragraph} | |||
| /> | |||
| ))} | |||
| key={index} | |||
| id={index} | |||
| title={item.title} | |||
| subtitle={item.subtitle} | |||
| paragraph={item.paragraph} | |||
| /> | |||
| ))} | |||
| </TimelineCardsWrapper2> | |||
| </div> | |||
| </div> | |||
| </Wrapper> | |||
| </div> | |||
| </PageLayout> | |||
| ); | |||
| @@ -15,6 +15,7 @@ import AboutUsSlider from '../components/shared/AboutUsSlider'; | |||
| import CardCareers2 from '../components/CardCareers2'; | |||
| import OrbitOnScroll from '../components/shared/graphics/OrbitOnScroll'; | |||
| import PageLayout from '../layout/PageLayout'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| // eslint-disable-next-line no-underscore-dangle | |||
| const _data = { | |||
| @@ -27,7 +28,8 @@ const _data = { | |||
| { | |||
| 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.', | |||
| 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.', | |||
| }, | |||
| ], | |||
| }, | |||
| @@ -36,48 +38,52 @@ const _data = { | |||
| subheading: 'Diligent life', | |||
| italic: { | |||
| heading: 'Life At diligent', | |||
| paragraph: 'From the start, you can expect to be challenged and supported. We provide a encouraged atmosphere with knowledgeable mentors to help you advance in your career. To create an inspiring work life, we collaborate as a team both inside and outside of the office.', | |||
| paragraph: | |||
| 'From the start, you can expect to be challenged and supported. We provide a encouraged atmosphere with knowledgeable mentors to help you advance in your career. To create an inspiring work life, we collaborate as a team both inside and outside of the office.', | |||
| heading2: 'What It Means to Work With Us', | |||
| }, | |||
| cards: [ | |||
| { | |||
| id: 1, | |||
| title: 'Shape the Future', | |||
| paragraph: 'We collaborate with business leaders and entrepreneurs to disrupt and push their industries forward. From startup ideas to enterprise-level product & software development, we work together as a team to transform our clients’ ideas into reality.', | |||
| paragraph: | |||
| 'We collaborate with business leaders and entrepreneurs to disrupt and push their industries forward. From startup ideas to enterprise-level product & software development, we work together as a team to transform our clients’ ideas into reality.', | |||
| }, | |||
| { | |||
| id: 2, | |||
| title: 'Life-Long Learning', | |||
| paragraph: 'We believe that learning is a journey that never ends. With us, you will have the opportunity to continuously learn in an environment surrounded by other highly skilled professionals with decades of experience. Also, there are several chances for you to develop through the use of various technologies, involvement in the product definition process, conference attendance, and more.', | |||
| paragraph: | |||
| 'We believe that learning is a journey that never ends. With us, you will have the opportunity to continuously learn in an environment surrounded by other highly skilled professionals with decades of experience. Also, there are several chances for you to develop through the use of various technologies, involvement in the product definition process, conference attendance, and more.', | |||
| }, | |||
| { | |||
| id: 3, | |||
| title: 'A Unique Culture', | |||
| paragraph: 'Everyone talks about a work-life balance, we do it - for two reasons. Firstly, we believe in an environment of happy people. Secondly, even if you’re highly productive, the only way to maintain productivity long-term is by taking time for the things that make you happy.', | |||
| paragraph: | |||
| 'Everyone talks about a work-life balance, we do it - for two reasons. Firstly, we believe in an environment of happy people. Secondly, even if you’re highly productive, the only way to maintain productivity long-term is by taking time for the things that make you happy.', | |||
| }, | |||
| { | |||
| id: 4, | |||
| title: 'Make the Impossible Better', | |||
| paragraph: 'If you have a mindset that is continuously focused on pushing through and beyond your boundaries, conquering a whole new challenge every day in an atmosphere where you constantly learn and improve, this is the place for you. We\'d love to learn more about you.', | |||
| paragraph: | |||
| "If you have a mindset that is continuously focused on pushing through and beyond your boundaries, conquering a whole new challenge every day in an atmosphere where you constantly learn and improve, this is the place for you. We'd love to learn more about you.", | |||
| }, | |||
| ], | |||
| }, | |||
| connect: { | |||
| heading: 'Connect and Grow With Us', | |||
| paragraph: 'At Diligent, we are passionately proud of our culture and feel that everyone, including those who are not yet on the team, should have the opportunity to experience it. Because of this, we participate in Open Doors. Our coworkers are actively involved in the local tech communities. We take satisfaction in giving back as well, assisting college students or seasoned professionals who want to start a career in IT.', | |||
| paragraph: | |||
| 'At Diligent, we are passionately proud of our culture and feel that everyone, including those who are not yet on the team, should have the opportunity to experience it. Because of this, we participate in Open Doors. Our coworkers are actively involved in the local tech communities. We take satisfaction in giving back as well, assisting college students or seasoned professionals who want to start a career in IT.', | |||
| subtitle: 'Check out how we have fun together!', | |||
| sliderImages: [ | |||
| ], | |||
| sliderImages: [], | |||
| }, | |||
| ActionCard: { | |||
| heading: 'Contact Us and Step up Your Career!', | |||
| paragraph: 'We are continuously on the lookout for talented people to grow our business.', | |||
| paragraph2: 'Don\'t be shy - Apply!', | |||
| paragraph: | |||
| 'We are continuously on the lookout for talented people to grow our business.', | |||
| paragraph2: "Don't be shy - Apply!", | |||
| primaryBtn: 'Apply', | |||
| secondaryBtn: 'About Us', | |||
| }, | |||
| }; | |||
| export default function Careers({ forwardedRef }) { | |||
| @@ -85,13 +91,16 @@ export default function Careers({ forwardedRef }) { | |||
| const [cntCareers, setCntCareers] = useState(''); | |||
| const [isLoaded, setIsLoaded] = useState(''); | |||
| const api_url = process.env.REACT_APP_API_URL; | |||
| useEffect(() => { | |||
| document.title = 'Careers'; | |||
| }, []); | |||
| //useAnalytics(); | |||
| useEffect(async () => { | |||
| var vid = document.getElementById('animation'); | |||
| vid.playbackRate = 2; | |||
| @@ -125,14 +134,22 @@ export default function Careers({ forwardedRef }) { | |||
| <PageLayout> | |||
| <div className="bg-white dark:bg-dg-primary-1700 w-full pt-90p overflow-hidden"> | |||
| <Wrapper padding={' py-90p'}> | |||
| <PageTitle heading={_data.heading.heading} subheading={_data.heading.subheading} left color /> | |||
| <h1 className="hidden">Careers - Join our Team</h1> | |||
| <PageTitle | |||
| heading={_data.heading.heading} | |||
| subheading={_data.heading.subheading} | |||
| left | |||
| color | |||
| /> | |||
| </Wrapper> | |||
| <Wrapper padding={' py-90p'}> | |||
| <div className="absolute hidden -ml-64 md:block"> | |||
| <OrbitOnScroll /> | |||
| </div> | |||
| <section id="jobs" className="flex items-center justify-center max-w-custom m-auto"> | |||
| <section | |||
| id="jobs" | |||
| className="flex items-center justify-center max-w-custom m-auto" | |||
| > | |||
| <div className="w-full"> | |||
| {/* {cntCareers.job.map(job => ( | |||
| <div key={job.id}> | |||
| @@ -157,17 +174,25 @@ export default function Careers({ forwardedRef }) { | |||
| </section> | |||
| </Wrapper> | |||
| <Wrapper bg padding={' py-90p'}> | |||
| <PageTitle left heading={_data.life.heading} subheading={_data.life.subheading} /> | |||
| <PageTitle | |||
| left | |||
| heading={_data.life.heading} | |||
| subheading={_data.life.subheading} | |||
| /> | |||
| <div className="my-90p"> | |||
| <div className="my-90p"> | |||
| <h3 className="title-italic">{_data.life.italic.heading}</h3> | |||
| <p className="paragraph"> | |||
| {_data.life.italic.paragraph} | |||
| </p> | |||
| <div className='w-full py-90p'> | |||
| <iframe className='m-auto w-[300px] h-[180px] md:w-[500px] md:h-[400px] lg:w-[800px] lg:h-[560px]' src="https://www.youtube.com/embed/PFHIqqHRS4s?controls=0" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe> | |||
| <p className="paragraph">{_data.life.italic.paragraph}</p> | |||
| <div className="w-full py-90p"> | |||
| <iframe | |||
| className="m-auto w-[300px] h-[180px] md:w-[500px] md:h-[400px] lg:w-[800px] lg:h-[560px]" | |||
| src="https://www.youtube.com/embed/PFHIqqHRS4s?controls=0" | |||
| title="YouTube video player" | |||
| frameBorder="0" | |||
| allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" | |||
| allowFullScreen | |||
| ></iframe> | |||
| </div> | |||
| </div> | |||
| <h3 className="title-italic">{_data.life.italic.heading2}</h3> | |||
| @@ -191,13 +216,11 @@ export default function Careers({ forwardedRef }) { | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </div> | |||
| </Wrapper> | |||
| <Wrapper padding={' py-90p'}> | |||
| <PageTitle heading={_data.connect.heading} color /> | |||
| <p className="paragraph my-32p">{_data.connect.paragraph}</p> | |||
| </Wrapper> | |||
| <Wrapper> | |||
| <section id="highlight" className="flex flex-col items-center justify-center"> | |||
| @@ -209,13 +232,18 @@ export default function Careers({ forwardedRef }) { | |||
| </Wrapper> | |||
| <Wrapper> | |||
| <div className="my-90p"> | |||
| <ActionCard title={_data.ActionCard.heading} text={_data.ActionCard.paragraph} btn1={_data.ActionCard.primaryBtn} btn2={_data.ActionCard.secondaryBtn} link1={'/contact'} link2={'/about'} text2={_data.ActionCard.paragraph2} /> | |||
| <ActionCard | |||
| title={_data.ActionCard.heading} | |||
| text={_data.ActionCard.paragraph} | |||
| btn1={_data.ActionCard.primaryBtn} | |||
| btn2={_data.ActionCard.secondaryBtn} | |||
| link1={'/contact'} | |||
| link2={'/about'} | |||
| text2={_data.ActionCard.paragraph2} | |||
| /> | |||
| </div> | |||
| </Wrapper> | |||
| </div> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -1,5 +1,7 @@ | |||
| import ActionCard from '../components/shared/ActionCard'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| import PageLayout from '../layout/PageLayout'; | |||
| import { useEffect } from 'react'; | |||
| const technologies = [ | |||
| { | |||
| @@ -37,6 +39,12 @@ const technologies = [ | |||
| ]; | |||
| export default function CaseStudy() { | |||
| useEffect(() => { | |||
| document.title = 'Case Studies'; | |||
| },[]); | |||
| //useAnalytics(); | |||
| return ( | |||
| <PageLayout> | |||
| <div className="bg-baby-blue dark:bg-dg-primary-1700 w-full pt-20 md:pt-24"> | |||
| @@ -9,30 +9,31 @@ import dataFactory from './../assets/icons/caseStudy/data-factory.svg'; | |||
| import { useEffect } from 'react'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import TechNuggets from '../components/shared/TechNuggets'; | |||
| import {motion} from 'framer-motion'; | |||
| import { motion } from 'framer-motion'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| const numbers = [ | |||
| { | |||
| value: 7, | |||
| static: '+', | |||
| title: 'Team Members' | |||
| title: 'Team Members', | |||
| }, | |||
| { | |||
| value: 100, | |||
| static: '+', | |||
| title: 'Users' | |||
| title: 'Users', | |||
| }, | |||
| { | |||
| value: 100, | |||
| value: '1,6m', | |||
| static: '+', | |||
| title: 'Transactions per Year' | |||
| } | |||
| ] | |||
| title: 'Transactions per Year', | |||
| }, | |||
| ]; | |||
| const _data = { | |||
| heading: { | |||
| subheading: 'Case Study', | |||
| heading: 'Bi Healthcare Solution', | |||
| heading: 'BI Healthcare Solution', | |||
| imgUrl: | |||
| 'https://lh3.googleusercontent.com/QkLcHNOGmWIB2t3fwZd69ZwJpHOYcTTAPmPs4zbjErDbp9nXbTw0vhktPCuCM2EWZUU=w2400', | |||
| paragraph: | |||
| @@ -116,153 +117,153 @@ const _data = { | |||
| }; | |||
| export default function CaseStudyBI() { | |||
| useEffect(() => { | |||
| document.title = 'Case Study: BI Healthcare Solution'; | |||
| },[]); | |||
| }, []); | |||
| //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://lh3.googleusercontent.com/QkLcHNOGmWIB2t3fwZd69ZwJpHOYcTTAPmPs4zbjErDbp9nXbTw0vhktPCuCM2EWZUU=w2400')] 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| </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' }} | |||
| <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://lh3.googleusercontent.com/QkLcHNOGmWIB2t3fwZd69ZwJpHOYcTTAPmPs4zbjErDbp9nXbTw0vhktPCuCM2EWZUU=w2400')] bg-cover" | |||
| > | |||
| {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 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| ))} | |||
| </motion.section> | |||
| </Wrapper> | |||
| {/* About the Client Section */} | |||
| <section id="client" className="flex flex-col items-center justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</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"> | |||
| {_data.about.country_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </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> | |||
| {/* About the Client Section */} | |||
| <section id="client" className="flex flex-col items-center justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h5 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.industry_name}</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"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.country_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.industry_name}</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| {/* 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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| </div> | |||
| </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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| {/* 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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| alt="Case Study main image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| {/* 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </section> | |||
| {/* Technologies Section */} | |||
| <section | |||
| id="technologies" | |||
| className="flex flex-col justify-center mt-16" | |||
| > | |||
| <div className="my-8 flex flex-col justify-center w-full max-w-custom m-auto px-8 xl:px-0"> | |||
| <div className="w-full"> | |||
| <h3 className="h3-heading">Technologies</h3> | |||
| {/* Technologies Section */} | |||
| <section id="technologies" className="flex flex-col justify-center 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={['Azure Data Factory','Azure SQL Server', 'Microsoft Power BI', '.Net Core', 'Azure App Services', 'Microsoft Power Automate','Azure Logic Apps','Azure Active Directory']} | |||
| /> | |||
| </div> | |||
| <TechNuggets tech={['.Net','Power BI','Power Automate','MSSQL','Data Factory']}/> | |||
| </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="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> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -8,8 +8,9 @@ import mssql from './../assets/icons/caseStudy/MSSQL.svg'; | |||
| import dataFactory from './../assets/icons/caseStudy/data-factory.svg'; | |||
| import { useEffect } from 'react'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import {motion} from 'framer-motion'; | |||
| import { motion } from 'framer-motion'; | |||
| import TechNuggets from '../components/shared/TechNuggets'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| const numbers = [ | |||
| { | |||
| @@ -35,8 +36,7 @@ const _data = { | |||
| heading: 'Centralized Monitoring System', | |||
| imgUrl: | |||
| 'https://lh4.googleusercontent.com/P93dPcW2bzA11uz2IhXYmSfEUQRzXjmeIH0HXv88s-dUmHQdtPtNonxeR-h0wqoPeMU=w2400', | |||
| paragraph: | |||
| 'Development of a centralized monitoring system for healthcare tools', | |||
| paragraph: 'Development of a centralized monitoring system for healthcare tools', | |||
| }, | |||
| about: { | |||
| @@ -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 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.", | |||
| }, | |||
| solution: { | |||
| @@ -120,19 +120,23 @@ const _data = { | |||
| }; | |||
| export default function CaseStudyCentralized() { | |||
| useEffect(() => { | |||
| document.title = 'Case Study: Centralized Monitoring System'; | |||
| },[]); | |||
| }, []); | |||
| //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 relative bg-cover bg-[url(\'https://lh4.googleusercontent.com/P93dPcW2bzA11uz2IhXYmSfEUQRzXjmeIH0HXv88s-dUmHQdtPtNonxeR-h0wqoPeMU=w2400\')] bg-no-repeat'} | |||
| > | |||
| id="heading" | |||
| className={ | |||
| "flex flex-col items-center justify-center m-auto py-16 md:py-32 relative bg-cover bg-[url('https://lh4.googleusercontent.com/P93dPcW2bzA11uz2IhXYmSfEUQRzXjmeIH0HXv88s-dUmHQdtPtNonxeR-h0wqoPeMU=w2400')] bg-no-repeat" | |||
| } | |||
| > | |||
| <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">{_data.heading.subheading}</h6> | |||
| @@ -142,7 +146,7 @@ export default function CaseStudyCentralized() { | |||
| </div> | |||
| </section> | |||
| {/* <Wrapper padding={' py-90p'}> | |||
| <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" | |||
| @@ -161,27 +165,27 @@ export default function CaseStudyCentralized() { | |||
| </div> | |||
| ))} | |||
| </motion.section> | |||
| </Wrapper> */} | |||
| </Wrapper> | |||
| {/* 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">{_data.about.heading}</h3> | |||
| <h2 className="h3-heading text-teal-600">{_data.about.heading}</h2> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</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"> | |||
| <h3 className="text-teal-600 font-semibold"> | |||
| {_data.about.country_heading} | |||
| </h5> | |||
| </h3> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h5 className="text-teal-600 font-semibold"> | |||
| <h3 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h5> | |||
| </h3> | |||
| <p className="mt-4">{_data.about.industry_name}</p> | |||
| </div> | |||
| </div> | |||
| @@ -200,9 +204,9 @@ export default function CaseStudyCentralized() { | |||
| {/* Challanges, Solution Section */} | |||
| <section | |||
| id="challanges_solution" | |||
| className="flex flex-col items-center justify-center mt-16" | |||
| > | |||
| 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> | |||
| @@ -219,10 +223,10 @@ export default function CaseStudyCentralized() { | |||
| </div> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| alt="Case Study main image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| src={_data.solution.imgUrl} | |||
| alt="Case Study main image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| </div> | |||
| </section> | |||
| @@ -234,22 +238,19 @@ export default function CaseStudyCentralized() { | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| ))} | |||
| </ul> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| {/* Technologies Section */} | |||
| <section | |||
| id="technologies" | |||
| className="flex flex-col items-center mt-16" | |||
| > | |||
| <div className="my-8 flex flex-col items-center w-full max-w-custom m-auto px-8 xl:px-0"> | |||
| {/*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']}/> | |||
| <TechNuggets tech={['.Net','MS SQL Server','JQuery','Power BI']} /> | |||
| </div> | |||
| </section> | |||
| @@ -257,13 +258,13 @@ export default function CaseStudyCentralized() { | |||
| <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'} | |||
| /> | |||
| 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> | |||
| @@ -5,26 +5,27 @@ import net from './../assets/icons/caseStudy/net.svg'; | |||
| import angular from './../assets/icons/caseStudy/angular.svg'; | |||
| import mssql from './../assets/icons/caseStudy/MSSQL.svg'; | |||
| import { useEffect } from 'react'; | |||
| import {motion} from 'framer-motion'; | |||
| import { motion } from 'framer-motion'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import TechNuggets from '../components/shared/TechNuggets'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| const numbers = [ | |||
| { | |||
| value: 5, | |||
| static: '+', | |||
| title: 'Team Members' | |||
| title: 'Team Members', | |||
| }, | |||
| { | |||
| value: 3, | |||
| static: '+', | |||
| title: 'Years Project Duration' | |||
| title: 'Years Project Duration', | |||
| }, | |||
| { | |||
| value: '1,6m', | |||
| static: '+', | |||
| title: 'Transactions per Year' | |||
| } | |||
| ] | |||
| title: 'Transactions per Year', | |||
| }, | |||
| ]; | |||
| const _data = { | |||
| heading: { | |||
| @@ -32,13 +33,13 @@ const _data = { | |||
| heading: 'Financial Engine', | |||
| imgUrl: | |||
| 'https://lh3.googleusercontent.com/pCtBoMQ4ea-MJV9TJzWucWkMOo0_0fetGCXblvffooAn9bG_ARbWNScRBBO16dNNrnk=w2400', | |||
| paragraph: | |||
| 'Implementing a system for financial system management', | |||
| paragraph: 'Implementing a system for financial system management', | |||
| }, | |||
| about: { | |||
| heading: 'About the Client', | |||
| paragraph: 'The client that deals with precious metals trading, storing, and investment had us expand the existing IT system with a sub-system that monitors and analyze the financial perspective of the business.', | |||
| paragraph: | |||
| 'The client that deals with precious metals trading, storing, and investment had us expand the existing IT system with a sub-system that monitors and analyze the financial perspective of the business.', | |||
| country_heading: 'Country', | |||
| country_name: 'USA', | |||
| industry_heading: 'Industry', | |||
| @@ -108,153 +109,152 @@ const _data = { | |||
| }; | |||
| export default function CaseStudyFinantial() { | |||
| useEffect(() => { | |||
| document.title = 'Case Study: Financial Engine'; | |||
| },[]); | |||
| }, []); | |||
| //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://lh3.googleusercontent.com/pCtBoMQ4ea-MJV9TJzWucWkMOo0_0fetGCXblvffooAn9bG_ARbWNScRBBO16dNNrnk=w2400')] 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| </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' }} | |||
| <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://lh3.googleusercontent.com/pCtBoMQ4ea-MJV9TJzWucWkMOo0_0fetGCXblvffooAn9bG_ARbWNScRBBO16dNNrnk=w2400')] bg-cover" | |||
| > | |||
| {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 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| ))} | |||
| </motion.section> | |||
| </Wrapper> | |||
| {/* About the Client Section */} | |||
| <section id="client" className="flex flex-col items-center justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</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"> | |||
| {_data.about.country_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </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> | |||
| {/* About the Client Section */} | |||
| <section id="client" className="flex flex-col items-center justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h5 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.industry_name}</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"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.country_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.industry_name}</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| {/* 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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| </div> | |||
| </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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| {/* 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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| alt="Case Study main image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| {/* 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| </div> | |||
| </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> | |||
| {/* 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)']} | |||
| /> | |||
| </div> | |||
| <TechNuggets tech={['.Net','Angular','MSSQL']}/> | |||
| </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="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> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -7,21 +7,23 @@ import powerAutomate from './../assets/icons/caseStudy/power-automate.svg'; | |||
| import mssql from './../assets/icons/caseStudy/MSSQL.svg'; | |||
| import dataFactory from './../assets/icons/caseStudy/data-factory.svg'; | |||
| import { useEffect } from 'react'; | |||
| import {motion} from 'framer-motion'; | |||
| import { motion } from 'framer-motion'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import TechNuggets from '../components/shared/TechNuggets'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| const numbers = [ | |||
| { | |||
| value: 6, | |||
| static: '+', | |||
| title: 'Team Members' | |||
| title: 'Team Members', | |||
| }, | |||
| { | |||
| value: 6, | |||
| static: '+', | |||
| title: 'Months Project duration' | |||
| title: 'Months Project duration', | |||
| }, | |||
| ] | |||
| ]; | |||
| const _data = { | |||
| heading: { | |||
| @@ -114,157 +116,153 @@ const _data = { | |||
| export default function CaseStudyResource() { | |||
| useEffect(() => { | |||
| document.title = 'Case Study: Resource Planning System'; | |||
| },[]); | |||
| }, []); | |||
| //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://lh3.googleusercontent.com/b9F35_JPlulVv0jS3UAYKJ2z6gz_AsWprQef_1wWTFGJlhEyLGfA1AthyUcdgrm1Qdk=w2400')] 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| </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' }} | |||
| <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://lh3.googleusercontent.com/b9F35_JPlulVv0jS3UAYKJ2z6gz_AsWprQef_1wWTFGJlhEyLGfA1AthyUcdgrm1Qdk=w2400')] bg-cover" | |||
| > | |||
| {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 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| ))} | |||
| </motion.section> | |||
| </Wrapper> | |||
| {/* About the Client Section */} | |||
| <section id="client" className="flex flex-col items-center justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</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">{_data.about.country_heading}</h5> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </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> | |||
| {/* About the Client Section */} | |||
| <section id="client" className="flex flex-col items-center justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h5 className="text-teal-600 font-semibold">{_data.about.industry_heading}</h5> | |||
| <p className="mt-4">{_data.about.industry_name}</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"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.country_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.industry_name}</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| {/* 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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| </div> | |||
| </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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| {/* 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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| alt="Case Study main image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| {/* 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| </div> | |||
| </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> | |||
| </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"> | |||
| {_data.technologies.map(technology => ( | |||
| <img | |||
| key={technology.id} | |||
| src={technology.link} | |||
| alt="Technology's image" | |||
| className="w-12 md:w-16 lg:w-20" | |||
| /> | |||
| ))} | |||
| {/* 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', 'MS SQL Server', 'React Native', 'React.JS']} | |||
| /> | |||
| </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="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> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -8,34 +8,35 @@ import jquery from './../assets/icons/caseStudy/jquery.svg'; | |||
| import react from './../assets/icons/caseStudy/react-native.svg'; | |||
| import mssql from './../assets/icons/caseStudy/MSSQL.svg'; | |||
| import { useEffect } from 'react'; | |||
| import {motion} from 'framer-motion'; | |||
| import { motion } from 'framer-motion'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| import TechNuggets from '../components/shared/TechNuggets'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| const numbers = [ | |||
| { | |||
| value: 5, | |||
| value: '10k', | |||
| static: '+', | |||
| title: 'Team Members' | |||
| title: 'Users', | |||
| }, | |||
| { | |||
| value: '3', | |||
| value: '230k', | |||
| static: '+', | |||
| title: 'Years Project duration' | |||
| title: 'Tests Ordered', | |||
| }, | |||
| { | |||
| value: '1,6m', | |||
| value: '200k', | |||
| static: '+', | |||
| title: 'Transactions per Year' | |||
| } | |||
| ] | |||
| title: 'Laboratory Results', | |||
| }, | |||
| ]; | |||
| const _data = { | |||
| heading: { | |||
| subheading: 'Case Study', | |||
| heading: 'Health Tracking Software', | |||
| imgUrl: strata, | |||
| paragraph: | |||
| 'COVID and Health Tracking Business Software', | |||
| paragraph: 'COVID and Health Tracking Business Software', | |||
| }, | |||
| about: { | |||
| @@ -64,8 +65,7 @@ const _data = { | |||
| heading: 'Solution', | |||
| paragraph: | |||
| 'To fulfill all requirements, we made a flexible application that consists of 3 parts: Admin portal, User portal, and User mobile app.', | |||
| imgUrl: | |||
| 'https://i.postimg.cc/L43QFftg/Strata-Small.png', | |||
| imgUrl: 'https://i.postimg.cc/L43QFftg/Strata-Small.png', | |||
| }, | |||
| results: { | |||
| @@ -111,160 +111,155 @@ const _data = { | |||
| }; | |||
| export default function CaseStudyStrata() { | |||
| useEffect(() => { | |||
| document.title = 'Case Study: Healthcare Tracking Software'; | |||
| },[]); | |||
| }, []); | |||
| //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 relative bg-cover bg-[url('https://i.postimg.cc/ZK08syVS/Strata.jpg')] bg-no-repeat"} | |||
| > | |||
| <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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| </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' }} | |||
| <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 relative bg-cover bg-[url('https://i.postimg.cc/ZK08syVS/Strata.jpg')] bg-no-repeat" | |||
| } | |||
| > | |||
| {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 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| ))} | |||
| </motion.section> | |||
| </Wrapper> */} | |||
| {/* 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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</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"> | |||
| {_data.about.country_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </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> | |||
| {/* 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"> | |||
| <h2 className="h3-heading text-teal-600">{_data.about.heading}</h2> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h5 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.industry_name}</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"> | |||
| <h3 className="text-teal-600 font-semibold"> | |||
| {_data.about.country_heading} | |||
| </h3> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h3 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h3> | |||
| <p className="mt-4">{_data.about.industry_name}</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| {/* 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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| </div> | |||
| </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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| {/* 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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| alt="Case Study main image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| {/* 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| </div> | |||
| </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> | |||
| </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"> | |||
| {_data.technologies.map(technology => ( | |||
| <img | |||
| key={technology.id} | |||
| src={technology.link} | |||
| alt="Technology's image" | |||
| className="w-12 md:w-16 lg:w-20" | |||
| /> | |||
| ))} | |||
| {/* 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={['C#', 'MVC', 'SQL','Ajax','React Native']} | |||
| /> | |||
| </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="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> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -8,25 +8,26 @@ import mssql from './../assets/icons/caseStudy/MSSQL.svg'; | |||
| import raspberry from './../assets/icons/caseStudy/raspberrypi.svg'; | |||
| import ionic from './../assets/icons/caseStudy/ionic.svg'; | |||
| import { useEffect } from 'react'; | |||
| import {motion} from 'framer-motion'; | |||
| import { motion } from 'framer-motion'; | |||
| import TechNuggets from '../components/shared/TechNuggets'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| const numbers = [ | |||
| { | |||
| value: 10, | |||
| static: '+', | |||
| title: 'Projects' | |||
| title: 'Projects', | |||
| }, | |||
| { | |||
| value: 10, | |||
| static: '+', | |||
| title: 'Years Project Duration' | |||
| title: 'Years Project Duration', | |||
| }, | |||
| { | |||
| value: '1,5m', | |||
| static: '+', | |||
| title: 'Transactions per Year' | |||
| } | |||
| ] | |||
| title: 'Transactions per Year', | |||
| }, | |||
| ]; | |||
| const _data = { | |||
| heading: { | |||
| @@ -123,153 +124,156 @@ const _data = { | |||
| export default function CaseStudyTicketing() { | |||
| useEffect(() => { | |||
| document.title = 'Case Study: Ticketing System For Passengers'; | |||
| },[]); | |||
| }, []); | |||
| //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://lh6.googleusercontent.com/iYNVVAYNEmKe9mY9IFK39EUWT2GZLjnZjF0QoghP8HV1_q8arGWEryvCcPhOWRzRTwU=w2400')] 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| <Wrapper padding={' py-90p'}> | |||
| <motion.section | |||
| id="status-numbers" | |||
| className="flex flex-col md:flex-row items-center justify-between w-full gap-90p px-90p" | |||
| initial={{ y: 60, opacity: 0 }} | |||
| whileInView={{ y: 0, opacity: 1 }} | |||
| transition={{ duration: 0.5, ease: 'easeOut' }} | |||
| <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://lh6.googleusercontent.com/iYNVVAYNEmKe9mY9IFK39EUWT2GZLjnZjF0QoghP8HV1_q8arGWEryvCcPhOWRzRTwU=w2400')] bg-cover" | |||
| > | |||
| {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 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">{_data.heading.subheading}</h6> | |||
| <h1 className="heading text-dg-secondary mt-2">{_data.heading.heading}</h1> | |||
| <p className="paragraph mt-4">{_data.heading.paragraph}</p> | |||
| </div> | |||
| ))} | |||
| </motion.section> | |||
| </Wrapper> | |||
| {/* About the Client Section */} | |||
| <section id="client" className="flex flex-col items-start justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</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"> | |||
| {_data.about.country_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </section> | |||
| <Wrapper padding={' py-90p'}> | |||
| <motion.section | |||
| id="status-numbers" | |||
| className="flex flex-col md:flex-row items-center 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-start justify-center"> | |||
| <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">{_data.about.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.about.paragraph}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h5 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h5> | |||
| <p className="mt-4">{_data.about.industry_name}</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"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.country_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.country_name}</p> | |||
| </div> | |||
| <div className="float-left md:float-right text-left md:text-right"> | |||
| <h4 className="text-teal-600 font-semibold"> | |||
| {_data.about.industry_heading} | |||
| </h4> | |||
| <p className="mt-4">{_data.about.industry_name}</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| {/* 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">{_data.domain.heading}</h3> | |||
| <p className="paragraph mt-4">{_data.domain.paragraph}</p> | |||
| </div> | |||
| </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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| {/* 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">{_data.challanges.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.challanges.paragraph} | |||
| </p> | |||
| </div> | |||
| <div className="mt-8"> | |||
| <h3 className="h3-heading">{_data.solution.heading}</h3> | |||
| <p className="text-sm text-dark-gray dark:text-white mt-4"> | |||
| {_data.solution.paragraph} | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| alt="Case Study main image" | |||
| className="text-center w-full md:w-1/2" | |||
| /> | |||
| </div> | |||
| <img | |||
| src={_data.solution.imgUrl} | |||
| 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| {/* 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">{_data.results.heading}</h3> | |||
| <ul className="list-disc paragraph mt-2 pl-8"> | |||
| {_data.results.list.map(item => ( | |||
| <li key={item.id}>{item.text}</li> | |||
| ))} | |||
| </ul> | |||
| </div> | |||
| </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> | |||
| {/* 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', 'Angular', 'Java', 'MSSQL', 'Ionic', 'Raspberry PI']} | |||
| /> | |||
| </div> | |||
| <TechNuggets tech={['.Net','Angular','Java','MSSQL','Ionic','Raspberry PI']}/> | |||
| </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="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> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -1,11 +1,7 @@ | |||
| import React, { useEffect, useState } from 'react'; | |||
| import Contact from '../components/shared/Contact'; | |||
| import PageLayout from '../layout/PageLayout'; | |||
| import Layout from '../layout/PageLayout'; | |||
| import axios from 'axios'; | |||
| import useDataApi from '../hooks/useDataApi'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| function ContactPage() { | |||
| const [data, setData] = useState(''); | |||
| @@ -14,18 +10,15 @@ function ContactPage() { | |||
| useEffect(() => { | |||
| document.title = 'Contact Us'; | |||
| },[]); | |||
| }, []); | |||
| return ( | |||
| <PageLayout> | |||
| <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> | |||
| <Contact defaultIndex={0} /> | |||
| </section> | |||
| </PageLayout> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -13,6 +13,7 @@ import CardsGrid from '../components/CardsGrid'; | |||
| import PageLayout from '../layout/PageLayout'; | |||
| import StrataThumb from './../assets/images/CaseStudy/StrataThumb.jpg'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| const _data = { | |||
| heading: { | |||
| @@ -24,159 +25,81 @@ const _data = { | |||
| cards: [ | |||
| { | |||
| id: 0, | |||
| title: 'Bi Healthcare Solution System', | |||
| imgUrl: | |||
| 'https://lh6.googleusercontent.com/D7N87i3udAln4YBp5SbaSI-9r2pVnnT5K2VT6p0G3dQanVgTMC2tdgz71PWOYco-7yQ=w2400', | |||
| title: 'BI Healthcare Solution System', | |||
| imgUrl: | |||
| 'https://lh6.googleusercontent.com/D7N87i3udAln4YBp5SbaSI-9r2pVnnT5K2VT6p0G3dQanVgTMC2tdgz71PWOYco-7yQ=w2400', | |||
| alt: 'BI Healthcare Solution System', | |||
| link: '/casestudybi', | |||
| }, | |||
| { | |||
| id: 1, | |||
| title: 'Resource Planning System', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/HLOh5coHfcEgDuftj1pOA9f1865xiIom5vyxTWNMKqMiivxL8Lg4c9ACzbfYYUdeuqQ=w2400', | |||
| 'https://lh5.googleusercontent.com/HLOh5coHfcEgDuftj1pOA9f1865xiIom5vyxTWNMKqMiivxL8Lg4c9ACzbfYYUdeuqQ=w2400', | |||
| alt: 'Resource Planning System', | |||
| link: '/casestudyresource', | |||
| }, | |||
| { | |||
| id: 2, | |||
| title: 'Ticketing System for Passengers', | |||
| imgUrl: | |||
| 'https://lh5.googleusercontent.com/f_G0H0C_qLHhsU8PBj6uTkNigzKiXzd24B_pgJ6UqVmBKlU2Lyxv2r5lf6uvY9d_0PY=w2400', | |||
| 'https://lh5.googleusercontent.com/f_G0H0C_qLHhsU8PBj6uTkNigzKiXzd24B_pgJ6UqVmBKlU2Lyxv2r5lf6uvY9d_0PY=w2400', | |||
| alt: 'Ticketing System for Passengers', | |||
| link: '/casestudyticketing', | |||
| }, | |||
| { | |||
| id: 3, | |||
| title: 'Financial Engine', | |||
| imgUrl: | |||
| 'https://lh3.googleusercontent.com/n-vcF1h8o4o3_CWZXoT-BQDLGFjL3_wt1twsDajycp8IhiiA2UkBoecsGd-ly_LRxJI=w2400', | |||
| 'https://lh3.googleusercontent.com/n-vcF1h8o4o3_CWZXoT-BQDLGFjL3_wt1twsDajycp8IhiiA2UkBoecsGd-ly_LRxJI=w2400', | |||
| alt: 'Financial Engine', | |||
| link: '/casestudyfinancial', | |||
| }, | |||
| { | |||
| id: 4, | |||
| title: 'Centralized Monitoring System', | |||
| imgUrl: | |||
| 'https://lh4.googleusercontent.com/CwrSwX4UVcU-nYhEk4wWqsK8TUJbt881kVx2i4ryXYJ3xIsN8d7F1bY0qO_0thHCbBM=w2400', | |||
| 'https://lh4.googleusercontent.com/CwrSwX4UVcU-nYhEk4wWqsK8TUJbt881kVx2i4ryXYJ3xIsN8d7F1bY0qO_0thHCbBM=w2400', | |||
| alt: 'Centralized Monitoring System', | |||
| link: '/casestudycentralized', | |||
| }, | |||
| { | |||
| id: 5, | |||
| title: 'Health Tracking Software', | |||
| imgUrl: 'https://i.postimg.cc/HsKGcXVv/Strata-Thumb.jpg', | |||
| alt: 'Health Tracking Software', | |||
| link: '/casestudystrata', | |||
| }, | |||
| ], | |||
| }; | |||
| export default function Portfolio() { | |||
| // const [cntPortfolio, setCntPortfolio] = useState(''); | |||
| // const [array,setArray] = useState([]); | |||
| // const [smallArray, setSmallArray] = useState([]); | |||
| // const [largeArray, setLargeArray] = useState([]); | |||
| // const [current, setCurrent] = useState([]); | |||
| // const [isLoaded, setIsLoaded] = useState(''); | |||
| // const api_url = process.env.REACT_APP_API_URL; | |||
| // const handleArray = (array) => { | |||
| // if (array == undefined) return; | |||
| // if (array.length <= 0) return; | |||
| // let left = false; | |||
| // let largeIndex = 4; | |||
| // let largeArray = []; | |||
| // let smallArray=[]; | |||
| // let current = []; | |||
| // //ako je desno onda je 5 | |||
| // //ako je levo onda je 7 | |||
| // array.map((item) => { | |||
| // if (item.attributes.IsLarge === true) { | |||
| // largeArray.push(item); | |||
| // } else { | |||
| // smallArray.push(item); | |||
| // } | |||
| // }) | |||
| // const index = smallArray.length + largeArray.length; | |||
| // for (let i = 0; i < index; i++) { | |||
| // //console.log(index) | |||
| // if(largeIndex - i == 0) { | |||
| // current.push(largeArray.shift()); | |||
| // left = !left; | |||
| // if(!left) { | |||
| // largeIndex = largeIndex + 6; | |||
| // } else { | |||
| // largeIndex = largeIndex + 4; | |||
| // } | |||
| // } else { | |||
| // current.push(smallArray.shift()); | |||
| // } | |||
| // } | |||
| // setCurrent(current); | |||
| // } | |||
| // useEffect(async () => { | |||
| // var vid = document.getElementById('animation'); | |||
| // vid.playbackRate = 2; | |||
| // var temp = []; | |||
| // axios | |||
| // .get( | |||
| // `${api_url}/api/portfoliopage?populate[0]=heading&&populate[1]=case_studies&&populate[2]=case_studies.img`, | |||
| // ) | |||
| // .then(res => { | |||
| // //console.log(res.data.data.attributes); | |||
| // setCntPortfolio(res.data.data.attributes); | |||
| // setArray(res.data.data.attributes.case_studies.data) | |||
| // setIsLoaded(true); | |||
| // }) | |||
| // .catch(err => { | |||
| // console.log(err); | |||
| // setIsLoaded(false); | |||
| // }); | |||
| // }, []); | |||
| // useEffect(() => { | |||
| // console.log(array); | |||
| // handleArray(array); | |||
| // },[array]); | |||
| // 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> | |||
| // ); | |||
| // } | |||
| useEffect(() => { | |||
| document.title = 'Case Studies'; | |||
| },[]); | |||
| }, []); | |||
| //useAnalytics(); | |||
| return ( | |||
| <PageLayout> | |||
| <div className="flex flex-col gap-90p pt-32"> | |||
| <Wrapper> | |||
| <div className="flex flex-col gap-8p"> | |||
| <PageTitle | |||
| heading={_data.heading.heading} | |||
| subheading={_data.heading.subheading} | |||
| left | |||
| color | |||
| /> | |||
| <p className="paragraph">{_data.heading.paragraph}</p> | |||
| </div> | |||
| </Wrapper> | |||
| <Wrapper> | |||
| <CardsGrid data={_data.cards} /> | |||
| </Wrapper> | |||
| </div> | |||
| <div className="flex flex-col gap-90p pt-32"> | |||
| <Wrapper> | |||
| <h1 className="hidden">Our Work - Case Studies</h1> | |||
| <div className="flex flex-col gap-8p"> | |||
| <PageTitle | |||
| heading={_data.heading.heading} | |||
| subheading={_data.heading.subheading} | |||
| left | |||
| color | |||
| /> | |||
| <p className="paragraph">{_data.heading.paragraph}</p> | |||
| </div> | |||
| </Wrapper> | |||
| <Wrapper> | |||
| <CardsGrid data={_data.cards} /> | |||
| </Wrapper> | |||
| </div> | |||
| </PageLayout> | |||
| ); | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| import React, { useEffect } from 'react'; | |||
| //import useAnalytics from '../hooks/useAnalytics'; | |||
| import Wrapper from '../layout/Wrapper'; | |||
| const PrivacyPolicy = () => { | |||
| @@ -7,6 +8,8 @@ const PrivacyPolicy = () => { | |||
| document.title = 'Privacy Policy'; | |||
| }, []); | |||
| //useAnalytics(); | |||
| return ( | |||
| <div className="mt-32p"> | |||
| @@ -10,140 +10,118 @@ import axios from 'axios'; | |||
| import Animation_Diligent from '../assets/animation_diligent.webm'; | |||
| import {ReactComponent as ProcessSvg} from './../assets/images/Process.svg'; | |||
| import { ReactComponent as ProcessSvg } from './../assets/images/Process.svg'; | |||
| import { m } from 'framer-motion'; | |||
| 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'; | |||
| const _data = { | |||
| heading : { | |||
| heading : "How We Do It?", | |||
| subheading: "Our Process", | |||
| paragraph: "We work with our clients to deliver the full software release lifecycle, from development to final rollout. We understand how important a good process is for success because our team members have deep backgrounds in product development. Our clients can rely on us for a complete software release solution that meets their needs and achieves their desired outcomes." | |||
| heading: { | |||
| heading: 'How We Do It?', | |||
| subheading: 'Our Process', | |||
| paragraph: | |||
| 'We work with our clients to deliver the full software release lifecycle, from development to final rollout. We understand how important a good process is for success because our team members have deep backgrounds in product development. Our clients can rely on us for a complete software release solution that meets their needs and achieves their desired outcomes.', | |||
| }, | |||
| processImg : { | |||
| url: "" | |||
| processImg: { | |||
| url: '', | |||
| }, | |||
| cards : [ | |||
| cards: [ | |||
| { | |||
| id: "1", | |||
| title: "Figure It Out", | |||
| id: '1', | |||
| title: 'Figure It Out', | |||
| subtitle: "After understanding the company's goals, we build a digital strategy.", | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "We collaborate with you to comprehend each business possibility associated with your project. Early technological issues are identified, followed by study and solution architecture. Our user-centric methodology yields results that are straightforward and interesting. To better understand your user base, we create Personas, Journey Mapping, and Usability Testing." | |||
| } | |||
| ] | |||
| paragraph: | |||
| 'We collaborate with you to comprehend each business possibility associated with your project. Early technological issues are identified, followed by study and solution architecture. Our user-centric methodology yields results that are straightforward and interesting. To better understand your user base, we create Personas, Journey Mapping, and Usability Testing.', | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| id: "2", | |||
| title: "Solution Design", | |||
| subtitle: "Align user and business strategies.", | |||
| id: '2', | |||
| title: 'Solution Design', | |||
| subtitle: 'Align user and business strategies.', | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "User experience (UX) User research inevitably leads to design. Know your users, their requirements, and their objectives. Our multidisciplinary design team creates system flows, journey maps, annotated wireframes, final UI designs, and click-model prototypes." | |||
| paragraph: | |||
| 'User experience (UX) User research inevitably leads to design. Know your users, their requirements, and their objectives. Our multidisciplinary design team creates system flows, journey maps, annotated wireframes, final UI designs, and click-model prototypes.', | |||
| }, | |||
| { | |||
| paragraph: "Close communication is essential for success here, and concepts are iterated on both our and your teams. We'll keep optimizing until we have the ideal design that meets your needs and those of your users." | |||
| } | |||
| ] | |||
| paragraph: | |||
| "Close communication is essential for success here, and concepts are iterated on both our and your teams. We'll keep optimizing until we have the ideal design that meets your needs and those of your users.", | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| id: "3", | |||
| title: "Build", | |||
| subtitle: "Delightful user experiences meet precise engineering.", | |||
| id: '3', | |||
| title: 'Build', | |||
| subtitle: 'Delightful user experiences meet precise engineering.', | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "Diligent can point you in the direction of the appropriate framework, language, and platform for your project, whether you already have a codebase or you start from scratch. Our talented group of developers includes computer scientists who are proficient in a variety of programming languages." | |||
| paragraph: | |||
| 'Diligent can point you in the direction of the appropriate framework, language, and platform for your project, whether you already have a codebase or you start from scratch. Our talented group of developers includes computer scientists who are proficient in a variety of programming languages.', | |||
| }, | |||
| { | |||
| paragraph: "We'll assist you in selecting the best technology for your project. We proceed with secure front-end, back-end, and full-stack development after deciding on the optimal strategy." | |||
| } | |||
| ] | |||
| paragraph: | |||
| "We'll assist you in selecting the best technology for your project. We proceed with secure front-end, back-end, and full-stack development after deciding on the optimal strategy.", | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| id: "4", | |||
| title: "QA Test", | |||
| subtitle: "Maximum efficiency, zero bugs.", | |||
| id: '4', | |||
| title: 'QA Test', | |||
| subtitle: 'Maximum efficiency, zero bugs.', | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "We take pride in creating quality software. Our code is scalable, reusable, readable, and high performing. We have developed extensive testing processes and standardized Diligent Software Practices thanks to our more than 7 years of expertise in software development with a wide range of projects." | |||
| } | |||
| ] | |||
| paragraph: | |||
| 'We take pride in creating quality software. Our code is scalable, reusable, readable, and high performing. We have developed extensive testing processes and standardized Diligent Software Practices thanks to our more than 7 years of expertise in software development with a wide range of projects.', | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| id: "5", | |||
| title: "Launch", | |||
| subtitle: "Go Live!", | |||
| id: '5', | |||
| title: 'Launch', | |||
| subtitle: 'Go Live!', | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "We are prepared to launch after all sprints have ended and User Acceptance Testing (UAT) has been successful. Hosting is often done with Amazon AWS, which allows us to quickly grow, backup, and manage your application." | |||
| paragraph: | |||
| 'We are prepared to launch after all sprints have ended and User Acceptance Testing (UAT) has been successful. Hosting is often done with Amazon AWS, which allows us to quickly grow, backup, and manage your application.', | |||
| }, | |||
| { | |||
| paragraph: "Depending on the nature and complexity of the project, one or several releases may be appropriate. Your time to market will be accelerated in either case by our agile development." | |||
| } | |||
| ] | |||
| paragraph: | |||
| 'Depending on the nature and complexity of the project, one or several releases may be appropriate. Your time to market will be accelerated in either case by our agile development.', | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| id: "6", | |||
| title: "Maintain and Improve", | |||
| subtitle: "Continually optimize and grow.", | |||
| id: '6', | |||
| title: 'Maintain and Improve', | |||
| subtitle: 'Continually optimize and grow.', | |||
| paragraphs: [ | |||
| { | |||
| paragraph: "We aim to provide long-term support for your program and establish ourselves as a reliable technological partner. We're here to support you while you update, monitor, and manage your app." | |||
| paragraph: | |||
| "We aim to provide long-term support for your program and establish ourselves as a reliable technological partner. We're here to support you while you update, monitor, and manage your app.", | |||
| }, | |||
| { | |||
| paragraph: "We will work with you to ensure stability and longevity. We also assist with new concepts and features. Allow us to assist you with your plan so you may keep wowing your users, clients, and investors." | |||
| } | |||
| ] | |||
| paragraph: | |||
| 'We will work with you to ensure stability and longevity. We also assist with new concepts and features. Allow us to assist you with your plan so you may keep wowing your users, clients, and investors.', | |||
| }, | |||
| ], | |||
| }, | |||
| ], | |||
| 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.", | |||
| primaryBtn: "Contact Us", | |||
| secondaryBtn: "Portfolio" | |||
| } | |||
| } | |||
| 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.', | |||
| primaryBtn: 'Contact Us', | |||
| secondaryBtn: 'Portfolio', | |||
| }, | |||
| }; | |||
| const ProcessPage = () => { | |||
| //const api_url = process.env.REACT_APP_API_URL; | |||
| // const [cntProcess, setCntProcess] = useState(''); | |||
| // const [isLoaded, setIsLoaded] = useState(''); | |||
| // useEffect(() => { | |||
| // var vid = document.getElementById('animation'); | |||
| // vid.playbackRate = 2; | |||
| // async function fetch() { | |||
| // axios | |||
| // .get( | |||
| // `${api_url}/api/process-page`, | |||
| // ) | |||
| // .then(res => { | |||
| // setCntProcess(res.data.data.attributes); | |||
| // //console.log(res.data.data.attributes); | |||
| // setIsLoaded(true); | |||
| // }) | |||
| // .catch(err => { | |||
| // console.log(err); | |||
| // setIsLoaded(false); | |||
| // }); | |||
| // } | |||
| // fetch(); | |||
| // }, []); | |||
| // 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> | |||
| // ); | |||
| // } | |||
| const [isMobile, setIsMobile] = useState(false); | |||
| @@ -151,7 +129,9 @@ const ProcessPage = () => { | |||
| useEffect(() => { | |||
| document.title = 'Process'; | |||
| },[]); | |||
| }, []); | |||
| //useAnalytics(); | |||
| useEffect(() => { | |||
| if (windowInfo.width < 1000) | |||
| @@ -162,59 +142,65 @@ const ProcessPage = () => { | |||
| return ( | |||
| <PageLayout> | |||
| <div className="pt-32"> | |||
| {_data.heading.heading && ( | |||
| <Wrapper> | |||
| <PageTitle | |||
| left | |||
| color | |||
| heading={_data.heading.heading} | |||
| subheading={_data.heading.subheading} | |||
| /> | |||
| {/* <div className="flex justify-center items-center mt-90p overflow-x-auto"> | |||
| <div className="pt-32"> | |||
| {_data.heading.heading && ( | |||
| <Wrapper> | |||
| <h1 className="hidden">Our Process - How We Do It?</h1> | |||
| <PageTitle | |||
| left | |||
| color | |||
| heading={_data.heading.heading} | |||
| subheading={_data.heading.subheading} | |||
| /> | |||
| {/* <div className="flex justify-center items-center mt-90p overflow-x-auto"> | |||
| <div className='w-full' draggable > | |||
| <ProcessSvg className='' /> | |||
| </div> | |||
| </div> */} | |||
| <div className="relative mx-auto my-32p md:my-90p"> | |||
| {!isMobile ? ( | |||
| <div className='w-full'> | |||
| <ProcessSvg className='' /> | |||
| </div> | |||
| ) : | |||
| ( | |||
| <div className='' > | |||
| <ProcessSlider/> | |||
| </div> | |||
| ) | |||
| } | |||
| </div> | |||
| <p className="my-90p">{_data.heading.paragraph}</p> | |||
| </Wrapper> | |||
| )} | |||
| <Wrapper bg padding={' py-90p'}> | |||
| {_data.cards.length > 0 && ( | |||
| <ProcessCardsWrapper> | |||
| {_data.cards.map((item, index) => ( | |||
| <ProcessCard | |||
| key={index} | |||
| id={item.id} | |||
| title={item.title} | |||
| subtitle={item.subtitle} | |||
| text={item.paragraphs} | |||
| numeric | |||
| /> | |||
| ))} | |||
| </ProcessCardsWrapper> | |||
| <div className="relative mx-auto my-32p md:my-90p"> | |||
| {!isMobile ? ( | |||
| <div className="w-full"> | |||
| <ProcessSvg className="" /> | |||
| </div> | |||
| ) : ( | |||
| <div className=""> | |||
| <ProcessSlider /> | |||
| </div> | |||
| )} | |||
| </div> | |||
| <p className="my-90p">{_data.heading.paragraph}</p> | |||
| </Wrapper> | |||
| )} | |||
| </Wrapper> | |||
| <Wrapper> | |||
| <div className='my-90p'> | |||
| <ActionCard title={_data.ActionCard.heading} text={_data.ActionCard.paragraph} btn1={_data.ActionCard.primaryBtn} btn2={_data.ActionCard.secondaryBtn} link1={"/contact"} link2={'/portfolio'}/> | |||
| </div> | |||
| </Wrapper> | |||
| </div> | |||
| <Wrapper bg padding={' py-90p'}> | |||
| {_data.cards.length > 0 && ( | |||
| <ProcessCardsWrapper> | |||
| {_data.cards.map((item, index) => ( | |||
| <ProcessCard | |||
| key={index} | |||
| id={item.id} | |||
| title={item.title} | |||
| subtitle={item.subtitle} | |||
| text={item.paragraphs} | |||
| numeric | |||
| /> | |||
| ))} | |||
| </ProcessCardsWrapper> | |||
| )} | |||
| </Wrapper> | |||
| <Wrapper> | |||
| <div className="my-90p"> | |||
| <ActionCard | |||
| title={_data.ActionCard.heading} | |||
| text={_data.ActionCard.paragraph} | |||
| btn1={_data.ActionCard.primaryBtn} | |||
| btn2={_data.ActionCard.secondaryBtn} | |||
| link1={'/contact'} | |||
| link2={'/portfolio'} | |||
| /> | |||
| </div> | |||
| </Wrapper> | |||
| </div> | |||
| </PageLayout> | |||
| ); | |||
| }; | |||
| @@ -0,0 +1,219 @@ | |||
| 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' | |||
| 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.' | |||
| } | |||
| ] | |||
| }; | |||
| const Segment = ({children}) => { | |||
| return ( | |||
| <div className='py-[48px] mx-auto w-full text-center'> | |||
| {children} | |||
| </div> | |||
| ); | |||
| } | |||
| 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}) => { | |||
| return ( | |||
| <div> | |||
| <h4 className='font-semibold text-title'>{title}</h4> | |||
| <p>{paragraph}</p> | |||
| </div> | |||
| ) | |||
| } | |||
| const WorkWithUs = () => { | |||
| //useAnalytics(); | |||
| 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} | |||
| /> | |||
| ))} | |||
| </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} | |||
| /> | |||
| ))} | |||
| </div> | |||
| </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> | |||
| </div> | |||
| ) | |||
| } | |||
| export default WorkWithUs | |||
| @@ -0,0 +1,109 @@ | |||
| import CaseStudy from "./components/CaseStudy"; | |||
| import About from "./pages/About"; | |||
| import Careers from "./pages/Careers"; | |||
| import CaseStudyBI from "./pages/CaseStudyBI"; | |||
| import CaseStudyCentralized from "./pages/CaseStudyCentralized"; | |||
| import CaseStudyFinantial from "./pages/CaseStudyFinantial"; | |||
| import CaseStudyResource from "./pages/CaseStudyResource"; | |||
| import CaseStudyStrata from "./pages/CaseStudyStrata"; | |||
| import CaseStudyTicketing from "./pages/CaseStudyTicketing"; | |||
| import ContactPage from "./pages/ContactPage"; | |||
| import Home from "./pages/Home"; | |||
| import Portfolio from "./pages/Portfolio"; | |||
| import PrivacyPolicy from "./pages/PrivacyPolicy"; | |||
| import ProcessPage from "./pages/ProcessPage"; | |||
| import WorkWithUs from "./pages/WorkWithUs"; | |||
| const routes = [ | |||
| { | |||
| path: '/', | |||
| component: <Home/>, | |||
| title: 'Diligent Software', | |||
| exact: true, | |||
| }, | |||
| { | |||
| path: '/workwithus', | |||
| component: <WorkWithUs/>, | |||
| title: 'Work with Us', | |||
| exact: true, | |||
| nav:true | |||
| }, | |||
| { | |||
| path: '/portfolio', | |||
| component: <Portfolio/>, | |||
| title: 'Case Studies', | |||
| exact: true, | |||
| nav:true | |||
| }, | |||
| { | |||
| path: '/process', | |||
| component: <ProcessPage />, | |||
| title: 'Process', | |||
| exact: true, | |||
| nav:true, | |||
| }, | |||
| { | |||
| path: '/casestudybi', | |||
| component: <CaseStudyBI/>, | |||
| title: 'BI Healthcare System', | |||
| exact: true | |||
| }, | |||
| { | |||
| path: '/casestudystrata', | |||
| component: <CaseStudyStrata/>, | |||
| title: 'Health Tracking Software', | |||
| exact: true | |||
| }, | |||
| { | |||
| path: '/casestudyfinancial', | |||
| component: <CaseStudyFinantial/>, | |||
| title: 'Financial Engine', | |||
| exact: true | |||
| }, | |||
| { | |||
| path: '/casestudyticketing', | |||
| component: <CaseStudyTicketing/>, | |||
| title: 'Ticketing System for Passengers', | |||
| exact: true | |||
| }, | |||
| { | |||
| path: '/casestudycentralized', | |||
| component: <CaseStudyCentralized/>, | |||
| title: 'Centralized Monitoring System', | |||
| exact: true | |||
| }, | |||
| { | |||
| path: '/casestudyresource', | |||
| component: <CaseStudyResource/>, | |||
| title: 'Resource Planning System', | |||
| exact: true | |||
| }, | |||
| { | |||
| path: '/careers', | |||
| component: <Careers/>, | |||
| title: 'Careers', | |||
| exact: true, | |||
| nav:true, | |||
| }, | |||
| { | |||
| path: '/about', | |||
| component: <About/>, | |||
| title: 'About Us', | |||
| exact: true, | |||
| nav:true, | |||
| }, | |||
| { | |||
| path: '/contact', | |||
| component: <ContactPage/>, | |||
| title: 'Contact Us', | |||
| exact: true, | |||
| }, | |||
| { | |||
| path: '/privacypolicy', | |||
| component: <PrivacyPolicy/>, | |||
| title: 'Privacy Policy', | |||
| exact: true | |||
| }, | |||
| ]; | |||
| export default routes; | |||
| @@ -8,7 +8,7 @@ | |||
| } | |||
| .subheading { | |||
| @apply tracking-widest text-subhead font-secondary uppercase text-dg-secondary font-semibold | |||
| @apply tracking-widest text-subhead font-secondary uppercase text-dg-secondary font-semibold; | |||
| } | |||
| .h3-heading { | |||
| @@ -19,18 +19,18 @@ | |||
| @apply border-dg-primary-1000 capitalize text-dg-primary-1000 hover:border-dg-primary-1200 hover:text-white transition-all hover:transition-all; | |||
| } | |||
| .paragraph { | |||
| @apply text-p-mobile md:text-p text-dark-gray dark:text-white | |||
| @apply text-p-mobile md:text-p text-dark-gray dark:text-white; | |||
| } | |||
| .display-number { | |||
| @apply text-display-numb font-secondary font-bold text-dg-primary-1000 | |||
| @apply text-display-numb font-secondary font-bold text-dg-primary-1000; | |||
| } | |||
| .number-title { | |||
| @apply text-title-24 font-secondary font-normal text-dark-gray | |||
| @apply text-title-24 font-secondary font-normal text-dark-gray; | |||
| } | |||
| .title-card { | |||
| @apply text-title font-semibold | |||
| @apply text-title font-semibold; | |||
| } | |||
| .subtitle-card-italic { | |||
| @@ -41,22 +41,21 @@ | |||
| } | |||
| .title-italic { | |||
| @apply text-italic-title text-dg-primary-400 font-semibold italic my-8p capitalize | |||
| @apply text-italic-title text-dg-primary-400 font-semibold italic my-8p capitalize; | |||
| } | |||
| } | |||
| .no-wrap { | |||
| flex-wrap: nowrap; | |||
| } | |||
| .no-wrap { | |||
| flex-wrap: nowrap; | |||
| } | |||
| .title-colored { | |||
| background: linear-gradient(270deg, #90278F 0%, #8468BF 100%); | |||
| -webkit-background-clip: text; | |||
| -webkit-text-fill-color: transparent; | |||
| background-clip: text; | |||
| } | |||
| .title-colored { | |||
| background: linear-gradient(270deg, #90278f 0%, #8468bf 100%); | |||
| -webkit-background-clip: text; | |||
| -webkit-text-fill-color: transparent; | |||
| background-clip: text; | |||
| } | |||
| .italic { | |||
| font-style: italic; | |||
| } | |||
| .italic { | |||
| font-style: italic; | |||
| } | |||
| @@ -9,7 +9,7 @@ module.exports = { | |||
| fontSize: { | |||
| 'head' : ['56px', { | |||
| letterSpacing: '1px', | |||
| lineHeight: '55px', | |||
| lineHeight: '74px', | |||
| }], | |||
| 'subhead' : ['12px', { | |||
| letterSpacing: '28px', | |||
| @@ -70,7 +70,12 @@ module.exports = { | |||
| 'display-numb' : ['56px', { | |||
| letterSpacing: '2px', | |||
| lineHeight: 'normal' | |||
| }], | |||
| 'subtitle-48' : ['48px', { | |||
| letterSpacing: '0px', | |||
| lineHeight: 'normal' | |||
| }] | |||
| }, | |||
| minHeight: { | |||
| '12': '3rem', | |||
| @@ -0,0 +1,12 @@ | |||
| #!/bin/sh | |||
| basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") | |||
| case `uname` in | |||
| *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; | |||
| esac | |||
| if [ -x "$basedir/node" ]; then | |||
| exec "$basedir/node" "$basedir/../loose-envify/cli.js" "$@" | |||
| else | |||
| exec node "$basedir/../loose-envify/cli.js" "$@" | |||
| fi | |||
| @@ -0,0 +1,17 @@ | |||
| @ECHO off | |||
| GOTO start | |||
| :find_dp0 | |||
| SET dp0=%~dp0 | |||
| EXIT /b | |||
| :start | |||
| SETLOCAL | |||
| CALL :find_dp0 | |||
| IF EXIST "%dp0%\node.exe" ( | |||
| SET "_prog=%dp0%\node.exe" | |||
| ) ELSE ( | |||
| SET "_prog=node" | |||
| SET PATHEXT=%PATHEXT:;.JS;=;% | |||
| ) | |||
| endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\loose-envify\cli.js" %* | |||
| @@ -0,0 +1,28 @@ | |||
| #!/usr/bin/env pwsh | |||
| $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent | |||
| $exe="" | |||
| if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { | |||
| # Fix case when both the Windows and Linux builds of Node | |||
| # are installed in the same directory | |||
| $exe=".exe" | |||
| } | |||
| $ret=0 | |||
| if (Test-Path "$basedir/node$exe") { | |||
| # Support pipeline input | |||
| if ($MyInvocation.ExpectingInput) { | |||
| $input | & "$basedir/node$exe" "$basedir/../loose-envify/cli.js" $args | |||
| } else { | |||
| & "$basedir/node$exe" "$basedir/../loose-envify/cli.js" $args | |||
| } | |||
| $ret=$LASTEXITCODE | |||
| } else { | |||
| # Support pipeline input | |||
| if ($MyInvocation.ExpectingInput) { | |||
| $input | & "node$exe" "$basedir/../loose-envify/cli.js" $args | |||
| } else { | |||
| & "node$exe" "$basedir/../loose-envify/cli.js" $args | |||
| } | |||
| $ret=$LASTEXITCODE | |||
| } | |||
| exit $ret | |||
| @@ -0,0 +1,72 @@ | |||
| { | |||
| "name": "website-new", | |||
| "lockfileVersion": 2, | |||
| "requires": true, | |||
| "packages": { | |||
| "node_modules/js-tokens": { | |||
| "version": "4.0.0", | |||
| "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", | |||
| "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", | |||
| "peer": true | |||
| }, | |||
| "node_modules/loose-envify": { | |||
| "version": "1.4.0", | |||
| "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", | |||
| "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", | |||
| "peer": true, | |||
| "dependencies": { | |||
| "js-tokens": "^3.0.0 || ^4.0.0" | |||
| }, | |||
| "bin": { | |||
| "loose-envify": "cli.js" | |||
| } | |||
| }, | |||
| "node_modules/object-assign": { | |||
| "version": "4.1.1", | |||
| "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", | |||
| "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", | |||
| "peer": true, | |||
| "engines": { | |||
| "node": ">=0.10.0" | |||
| } | |||
| }, | |||
| "node_modules/prop-types": { | |||
| "version": "15.8.1", | |||
| "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", | |||
| "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", | |||
| "peer": true, | |||
| "dependencies": { | |||
| "loose-envify": "^1.4.0", | |||
| "object-assign": "^4.1.1", | |||
| "react-is": "^16.13.1" | |||
| } | |||
| }, | |||
| "node_modules/react": { | |||
| "version": "18.2.0", | |||
| "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", | |||
| "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", | |||
| "peer": true, | |||
| "dependencies": { | |||
| "loose-envify": "^1.1.0" | |||
| }, | |||
| "engines": { | |||
| "node": ">=0.10.0" | |||
| } | |||
| }, | |||
| "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-is": { | |||
| "version": "16.13.1", | |||
| "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", | |||
| "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", | |||
| "peer": true | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,151 @@ | |||
| ### Version 4.0.0 (2018-01-28) ### | |||
| - Added: Support for ES2018. The only change needed was recognizing the `s` | |||
| regex flag. | |||
| - Changed: _All_ tokens returned by the `matchToToken` function now have a | |||
| `closed` property. It is set to `undefined` for the tokens where “closed” | |||
| doesn’t make sense. This means that all tokens objects have the same shape, | |||
| which might improve performance. | |||
| These are the breaking changes: | |||
| - `'/a/s'.match(jsTokens)` no longer returns `['/', 'a', '/', 's']`, but | |||
| `['/a/s']`. (There are of course other variations of this.) | |||
| - Code that rely on some token objects not having the `closed` property could | |||
| now behave differently. | |||
| ### Version 3.0.2 (2017-06-28) ### | |||
| - No code changes. Just updates to the readme. | |||
| ### Version 3.0.1 (2017-01-30) ### | |||
| - Fixed: ES2015 unicode escapes with more than 6 hex digits are now matched | |||
| correctly. | |||
| ### Version 3.0.0 (2017-01-11) ### | |||
| This release contains one breaking change, that should [improve performance in | |||
| V8][v8-perf]: | |||
| > So how can you, as a JavaScript developer, ensure that your RegExps are fast? | |||
| > If you are not interested in hooking into RegExp internals, make sure that | |||
| > neither the RegExp instance, nor its prototype is modified in order to get the | |||
| > best performance: | |||
| > | |||
| > ```js | |||
| > var re = /./g; | |||
| > re.exec(''); // Fast path. | |||
| > re.new_property = 'slow'; | |||
| > ``` | |||
| This module used to export a single regex, with `.matchToToken` bolted | |||
| on, just like in the above example. This release changes the exports of | |||
| the module to avoid this issue. | |||
| Before: | |||
| ```js | |||
| import jsTokens from "js-tokens" | |||
| // or: | |||
| var jsTokens = require("js-tokens") | |||
| var matchToToken = jsTokens.matchToToken | |||
| ``` | |||
| After: | |||
| ```js | |||
| import jsTokens, {matchToToken} from "js-tokens" | |||
| // or: | |||
| var jsTokens = require("js-tokens").default | |||
| var matchToToken = require("js-tokens").matchToToken | |||
| ``` | |||
| [v8-perf]: http://v8project.blogspot.se/2017/01/speeding-up-v8-regular-expressions.html | |||
| ### Version 2.0.0 (2016-06-19) ### | |||
| - Added: Support for ES2016. In other words, support for the `**` exponentiation | |||
| operator. | |||
| These are the breaking changes: | |||
| - `'**'.match(jsTokens)` no longer returns `['*', '*']`, but `['**']`. | |||
| - `'**='.match(jsTokens)` no longer returns `['*', '*=']`, but `['**=']`. | |||
| ### Version 1.0.3 (2016-03-27) ### | |||
| - Improved: Made the regex ever so slightly smaller. | |||
| - Updated: The readme. | |||
| ### Version 1.0.2 (2015-10-18) ### | |||
| - Improved: Limited npm package contents for a smaller download. Thanks to | |||
| @zertosh! | |||
| ### Version 1.0.1 (2015-06-20) ### | |||
| - Fixed: Declared an undeclared variable. | |||
| ### Version 1.0.0 (2015-02-26) ### | |||
| - Changed: Merged the 'operator' and 'punctuation' types into 'punctuator'. That | |||
| type is now equivalent to the Punctuator token in the ECMAScript | |||
| specification. (Backwards-incompatible change.) | |||
| - Fixed: A `-` followed by a number is now correctly matched as a punctuator | |||
| followed by a number. It used to be matched as just a number, but there is no | |||
| such thing as negative number literals. (Possibly backwards-incompatible | |||
| change.) | |||
| ### Version 0.4.1 (2015-02-21) ### | |||
| - Added: Support for the regex `u` flag. | |||
| ### Version 0.4.0 (2015-02-21) ### | |||
| - Improved: `jsTokens.matchToToken` performance. | |||
| - Added: Support for octal and binary number literals. | |||
| - Added: Support for template strings. | |||
| ### Version 0.3.1 (2015-01-06) ### | |||
| - Fixed: Support for unicode spaces. They used to be allowed in names (which is | |||
| very confusing), and some unicode newlines were wrongly allowed in strings and | |||
| regexes. | |||
| ### Version 0.3.0 (2014-12-19) ### | |||
| - Changed: The `jsTokens.names` array has been replaced with the | |||
| `jsTokens.matchToToken` function. The capturing groups of `jsTokens` are no | |||
| longer part of the public API; instead use said function. See this [gist] for | |||
| an example. (Backwards-incompatible change.) | |||
| - Changed: The empty string is now considered an “invalid” token, instead an | |||
| “empty” token (its own group). (Backwards-incompatible change.) | |||
| - Removed: component support. (Backwards-incompatible change.) | |||
| [gist]: https://gist.github.com/lydell/be49dbf80c382c473004 | |||
| ### Version 0.2.0 (2014-06-19) ### | |||
| - Changed: Match ES6 function arrows (`=>`) as an operator, instead of its own | |||
| category (“functionArrow”), for simplicity. (Backwards-incompatible change.) | |||
| - Added: ES6 splats (`...`) are now matched as an operator (instead of three | |||
| punctuations). (Backwards-incompatible change.) | |||
| ### Version 0.1.0 (2014-03-08) ### | |||
| - Initial release. | |||
| @@ -0,0 +1,21 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in | |||
| all copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| THE SOFTWARE. | |||
| @@ -0,0 +1,240 @@ | |||
| Overview [](https://travis-ci.org/lydell/js-tokens) | |||
| ======== | |||
| A regex that tokenizes JavaScript. | |||
| ```js | |||
| var jsTokens = require("js-tokens").default | |||
| var jsString = "var foo=opts.foo;\n..." | |||
| jsString.match(jsTokens) | |||
| // ["var", " ", "foo", "=", "opts", ".", "foo", ";", "\n", ...] | |||
| ``` | |||
| Installation | |||
| ============ | |||
| `npm install js-tokens` | |||
| ```js | |||
| import jsTokens from "js-tokens" | |||
| // or: | |||
| var jsTokens = require("js-tokens").default | |||
| ``` | |||
| Usage | |||
| ===== | |||
| ### `jsTokens` ### | |||
| A regex with the `g` flag that matches JavaScript tokens. | |||
| The regex _always_ matches, even invalid JavaScript and the empty string. | |||
| The next match is always directly after the previous. | |||
| ### `var token = matchToToken(match)` ### | |||
| ```js | |||
| import {matchToToken} from "js-tokens" | |||
| // or: | |||
| var matchToToken = require("js-tokens").matchToToken | |||
| ``` | |||
| Takes a `match` returned by `jsTokens.exec(string)`, and returns a `{type: | |||
| String, value: String}` object. The following types are available: | |||
| - string | |||
| - comment | |||
| - regex | |||
| - number | |||
| - name | |||
| - punctuator | |||
| - whitespace | |||
| - invalid | |||
| Multi-line comments and strings also have a `closed` property indicating if the | |||
| token was closed or not (see below). | |||
| Comments and strings both come in several flavors. To distinguish them, check if | |||
| the token starts with `//`, `/*`, `'`, `"` or `` ` ``. | |||
| Names are ECMAScript IdentifierNames, that is, including both identifiers and | |||
| keywords. You may use [is-keyword-js] to tell them apart. | |||
| Whitespace includes both line terminators and other whitespace. | |||
| [is-keyword-js]: https://github.com/crissdev/is-keyword-js | |||
| ECMAScript support | |||
| ================== | |||
| The intention is to always support the latest ECMAScript version whose feature | |||
| set has been finalized. | |||
| If adding support for a newer version requires changes, a new version with a | |||
| major verion bump will be released. | |||
| Currently, ECMAScript 2018 is supported. | |||
| Invalid code handling | |||
| ===================== | |||
| Unterminated strings are still matched as strings. JavaScript strings cannot | |||
| contain (unescaped) newlines, so unterminated strings simply end at the end of | |||
| the line. Unterminated template strings can contain unescaped newlines, though, | |||
| so they go on to the end of input. | |||
| Unterminated multi-line comments are also still matched as comments. They | |||
| simply go on to the end of the input. | |||
| Unterminated regex literals are likely matched as division and whatever is | |||
| inside the regex. | |||
| Invalid ASCII characters have their own capturing group. | |||
| Invalid non-ASCII characters are treated as names, to simplify the matching of | |||
| names (except unicode spaces which are treated as whitespace). Note: See also | |||
| the [ES2018](#es2018) section. | |||
| Regex literals may contain invalid regex syntax. They are still matched as | |||
| regex literals. They may also contain repeated regex flags, to keep the regex | |||
| simple. | |||
| Strings may contain invalid escape sequences. | |||
| Limitations | |||
| =========== | |||
| Tokenizing JavaScript using regexes—in fact, _one single regex_—won’t be | |||
| perfect. But that’s not the point either. | |||
| You may compare jsTokens with [esprima] by using `esprima-compare.js`. | |||
| See `npm run esprima-compare`! | |||
| [esprima]: http://esprima.org/ | |||
| ### Template string interpolation ### | |||
| Template strings are matched as single tokens, from the starting `` ` `` to the | |||
| ending `` ` ``, including interpolations (whose tokens are not matched | |||
| individually). | |||
| Matching template string interpolations requires recursive balancing of `{` and | |||
| `}`—something that JavaScript regexes cannot do. Only one level of nesting is | |||
| supported. | |||
| ### Division and regex literals collision ### | |||
| Consider this example: | |||
| ```js | |||
| var g = 9.82 | |||
| var number = bar / 2/g | |||
| var regex = / 2/g | |||
| ``` | |||
| A human can easily understand that in the `number` line we’re dealing with | |||
| division, and in the `regex` line we’re dealing with a regex literal. How come? | |||
| Because humans can look at the whole code to put the `/` characters in context. | |||
| A JavaScript regex cannot. It only sees forwards. (Well, ES2018 regexes can also | |||
| look backwards. See the [ES2018](#es2018) section). | |||
| When the `jsTokens` regex scans throught the above, it will see the following | |||
| at the end of both the `number` and `regex` rows: | |||
| ```js | |||
| / 2/g | |||
| ``` | |||
| It is then impossible to know if that is a regex literal, or part of an | |||
| expression dealing with division. | |||
| Here is a similar case: | |||
| ```js | |||
| foo /= 2/g | |||
| foo(/= 2/g) | |||
| ``` | |||
| The first line divides the `foo` variable with `2/g`. The second line calls the | |||
| `foo` function with the regex literal `/= 2/g`. Again, since `jsTokens` only | |||
| sees forwards, it cannot tell the two cases apart. | |||
| There are some cases where we _can_ tell division and regex literals apart, | |||
| though. | |||
| First off, we have the simple cases where there’s only one slash in the line: | |||
| ```js | |||
| var foo = 2/g | |||
| foo /= 2 | |||
| ``` | |||
| Regex literals cannot contain newlines, so the above cases are correctly | |||
| identified as division. Things are only problematic when there are more than | |||
| one non-comment slash in a single line. | |||
| Secondly, not every character is a valid regex flag. | |||
| ```js | |||
| var number = bar / 2/e | |||
| ``` | |||
| The above example is also correctly identified as division, because `e` is not a | |||
| valid regex flag. I initially wanted to future-proof by allowing `[a-zA-Z]*` | |||
| (any letter) as flags, but it is not worth it since it increases the amount of | |||
| ambigous cases. So only the standard `g`, `m`, `i`, `y` and `u` flags are | |||
| allowed. This means that the above example will be identified as division as | |||
| long as you don’t rename the `e` variable to some permutation of `gmiyus` 1 to 6 | |||
| characters long. | |||
| Lastly, we can look _forward_ for information. | |||
| - If the token following what looks like a regex literal is not valid after a | |||
| regex literal, but is valid in a division expression, then the regex literal | |||
| is treated as division instead. For example, a flagless regex cannot be | |||
| followed by a string, number or name, but all of those three can be the | |||
| denominator of a division. | |||
| - Generally, if what looks like a regex literal is followed by an operator, the | |||
| regex literal is treated as division instead. This is because regexes are | |||
| seldomly used with operators (such as `+`, `*`, `&&` and `==`), but division | |||
| could likely be part of such an expression. | |||
| Please consult the regex source and the test cases for precise information on | |||
| when regex or division is matched (should you need to know). In short, you | |||
| could sum it up as: | |||
| If the end of a statement looks like a regex literal (even if it isn’t), it | |||
| will be treated as one. Otherwise it should work as expected (if you write sane | |||
| code). | |||
| ### ES2018 ### | |||
| ES2018 added some nice regex improvements to the language. | |||
| - [Unicode property escapes] should allow telling names and invalid non-ASCII | |||
| characters apart without blowing up the regex size. | |||
| - [Lookbehind assertions] should allow matching telling division and regex | |||
| literals apart in more cases. | |||
| - [Named capture groups] might simplify some things. | |||
| These things would be nice to do, but are not critical. They probably have to | |||
| wait until the oldest maintained Node.js LTS release supports those features. | |||
| [Unicode property escapes]: http://2ality.com/2017/07/regexp-unicode-property-escapes.html | |||
| [Lookbehind assertions]: http://2ality.com/2017/05/regexp-lookbehind-assertions.html | |||
| [Named capture groups]: http://2ality.com/2017/05/regexp-named-capture-groups.html | |||
| License | |||
| ======= | |||
| [MIT](LICENSE). | |||
| @@ -0,0 +1,23 @@ | |||
| // Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell | |||
| // License: MIT. (See LICENSE.) | |||
| Object.defineProperty(exports, "__esModule", { | |||
| value: true | |||
| }) | |||
| // This regex comes from regex.coffee, and is inserted here by generate-index.js | |||
| // (run `npm run build`). | |||
| exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g | |||
| exports.matchToToken = function(match) { | |||
| var token = {type: "invalid", value: match[0], closed: undefined} | |||
| if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4]) | |||
| else if (match[ 5]) token.type = "comment" | |||
| else if (match[ 6]) token.type = "comment", token.closed = !!match[7] | |||
| else if (match[ 8]) token.type = "regex" | |||
| else if (match[ 9]) token.type = "number" | |||
| else if (match[10]) token.type = "name" | |||
| else if (match[11]) token.type = "punctuator" | |||
| else if (match[12]) token.type = "whitespace" | |||
| return token | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| { | |||
| "name": "js-tokens", | |||
| "version": "4.0.0", | |||
| "author": "Simon Lydell", | |||
| "license": "MIT", | |||
| "description": "A regex that tokenizes JavaScript.", | |||
| "keywords": [ | |||
| "JavaScript", | |||
| "js", | |||
| "token", | |||
| "tokenize", | |||
| "regex" | |||
| ], | |||
| "files": [ | |||
| "index.js" | |||
| ], | |||
| "repository": "lydell/js-tokens", | |||
| "scripts": { | |||
| "test": "mocha --ui tdd", | |||
| "esprima-compare": "node esprima-compare ./index.js everything.js/es5.js", | |||
| "build": "node generate-index.js", | |||
| "dev": "npm run build && npm test" | |||
| }, | |||
| "devDependencies": { | |||
| "coffeescript": "2.1.1", | |||
| "esprima": "4.0.0", | |||
| "everything.js": "1.0.3", | |||
| "mocha": "5.0.0" | |||
| } | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) 2015 Andres Suarez <zertosh@gmail.com> | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in | |||
| all copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| THE SOFTWARE. | |||
| @@ -0,0 +1,45 @@ | |||
| # loose-envify | |||
| [](https://travis-ci.org/zertosh/loose-envify) | |||
| Fast (and loose) selective `process.env` replacer using [js-tokens](https://github.com/lydell/js-tokens) instead of an AST. Works just like [envify](https://github.com/hughsk/envify) but much faster. | |||
| ## Gotchas | |||
| * Doesn't handle broken syntax. | |||
| * Doesn't look inside embedded expressions in template strings. | |||
| - **this won't work:** | |||
| ```js | |||
| console.log(`the current env is ${process.env.NODE_ENV}`); | |||
| ``` | |||
| * Doesn't replace oddly-spaced or oddly-commented expressions. | |||
| - **this won't work:** | |||
| ```js | |||
| console.log(process./*won't*/env./*work*/NODE_ENV); | |||
| ``` | |||
| ## Usage/Options | |||
| loose-envify has the exact same interface as [envify](https://github.com/hughsk/envify), including the CLI. | |||
| ## Benchmark | |||
| ``` | |||
| envify: | |||
| $ for i in {1..5}; do node bench/bench.js 'envify'; done | |||
| 708ms | |||
| 727ms | |||
| 791ms | |||
| 719ms | |||
| 720ms | |||
| loose-envify: | |||
| $ for i in {1..5}; do node bench/bench.js '../'; done | |||
| 51ms | |||
| 52ms | |||
| 52ms | |||
| 52ms | |||
| 52ms | |||
| ``` | |||
| @@ -0,0 +1,16 @@ | |||
| #!/usr/bin/env node | |||
| 'use strict'; | |||
| var looseEnvify = require('./'); | |||
| var fs = require('fs'); | |||
| if (process.argv[2]) { | |||
| fs.createReadStream(process.argv[2], {encoding: 'utf8'}) | |||
| .pipe(looseEnvify(process.argv[2])) | |||
| .pipe(process.stdout); | |||
| } else { | |||
| process.stdin.resume() | |||
| process.stdin | |||
| .pipe(looseEnvify(__filename)) | |||
| .pipe(process.stdout); | |||
| } | |||
| @@ -0,0 +1,4 @@ | |||
| // envify compatibility | |||
| 'use strict'; | |||
| module.exports = require('./loose-envify'); | |||
| @@ -0,0 +1,3 @@ | |||
| 'use strict'; | |||
| module.exports = require('./loose-envify')(process.env); | |||
| @@ -0,0 +1,36 @@ | |||
| 'use strict'; | |||
| var stream = require('stream'); | |||
| var util = require('util'); | |||
| var replace = require('./replace'); | |||
| var jsonExtRe = /\.json$/; | |||
| module.exports = function(rootEnv) { | |||
| rootEnv = rootEnv || process.env; | |||
| return function (file, trOpts) { | |||
| if (jsonExtRe.test(file)) { | |||
| return stream.PassThrough(); | |||
| } | |||
| var envs = trOpts ? [rootEnv, trOpts] : [rootEnv]; | |||
| return new LooseEnvify(envs); | |||
| }; | |||
| }; | |||
| function LooseEnvify(envs) { | |||
| stream.Transform.call(this); | |||
| this._data = ''; | |||
| this._envs = envs; | |||
| } | |||
| util.inherits(LooseEnvify, stream.Transform); | |||
| LooseEnvify.prototype._transform = function(buf, enc, cb) { | |||
| this._data += buf; | |||
| cb(); | |||
| }; | |||
| LooseEnvify.prototype._flush = function(cb) { | |||
| var replaced = replace(this._data, this._envs); | |||
| this.push(replaced); | |||
| cb(); | |||
| }; | |||
| @@ -0,0 +1,36 @@ | |||
| { | |||
| "name": "loose-envify", | |||
| "version": "1.4.0", | |||
| "description": "Fast (and loose) selective `process.env` replacer using js-tokens instead of an AST", | |||
| "keywords": [ | |||
| "environment", | |||
| "variables", | |||
| "browserify", | |||
| "browserify-transform", | |||
| "transform", | |||
| "source", | |||
| "configuration" | |||
| ], | |||
| "homepage": "https://github.com/zertosh/loose-envify", | |||
| "license": "MIT", | |||
| "author": "Andres Suarez <zertosh@gmail.com>", | |||
| "main": "index.js", | |||
| "bin": { | |||
| "loose-envify": "cli.js" | |||
| }, | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git://github.com/zertosh/loose-envify.git" | |||
| }, | |||
| "scripts": { | |||
| "test": "tap test/*.js" | |||
| }, | |||
| "dependencies": { | |||
| "js-tokens": "^3.0.0 || ^4.0.0" | |||
| }, | |||
| "devDependencies": { | |||
| "browserify": "^13.1.1", | |||
| "envify": "^3.4.0", | |||
| "tap": "^8.0.0" | |||
| } | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| 'use strict'; | |||
| var jsTokens = require('js-tokens').default; | |||
| var processEnvRe = /\bprocess\.env\.[_$a-zA-Z][$\w]+\b/; | |||
| var spaceOrCommentRe = /^(?:\s|\/[/*])/; | |||
| function replace(src, envs) { | |||
| if (!processEnvRe.test(src)) { | |||
| return src; | |||
| } | |||
| var out = []; | |||
| var purge = envs.some(function(env) { | |||
| return env._ && env._.indexOf('purge') !== -1; | |||
| }); | |||
| jsTokens.lastIndex = 0 | |||
| var parts = src.match(jsTokens); | |||
| for (var i = 0; i < parts.length; i++) { | |||
| if (parts[i ] === 'process' && | |||
| parts[i + 1] === '.' && | |||
| parts[i + 2] === 'env' && | |||
| parts[i + 3] === '.') { | |||
| var prevCodeToken = getAdjacentCodeToken(-1, parts, i); | |||
| var nextCodeToken = getAdjacentCodeToken(1, parts, i + 4); | |||
| var replacement = getReplacementString(envs, parts[i + 4], purge); | |||
| if (prevCodeToken !== '.' && | |||
| nextCodeToken !== '.' && | |||
| nextCodeToken !== '=' && | |||
| typeof replacement === 'string') { | |||
| out.push(replacement); | |||
| i += 4; | |||
| continue; | |||
| } | |||
| } | |||
| out.push(parts[i]); | |||
| } | |||
| return out.join(''); | |||
| } | |||
| function getAdjacentCodeToken(dir, parts, i) { | |||
| while (true) { | |||
| var part = parts[i += dir]; | |||
| if (!spaceOrCommentRe.test(part)) { | |||
| return part; | |||
| } | |||
| } | |||
| } | |||
| function getReplacementString(envs, name, purge) { | |||
| for (var j = 0; j < envs.length; j++) { | |||
| var env = envs[j]; | |||
| if (typeof env[name] !== 'undefined') { | |||
| return JSON.stringify(env[name]); | |||
| } | |||
| } | |||
| if (purge) { | |||
| return 'undefined'; | |||
| } | |||
| } | |||
| module.exports = replace; | |||
| @@ -0,0 +1,90 @@ | |||
| /* | |||
| object-assign | |||
| (c) Sindre Sorhus | |||
| @license MIT | |||
| */ | |||
| 'use strict'; | |||
| /* eslint-disable no-unused-vars */ | |||
| var getOwnPropertySymbols = Object.getOwnPropertySymbols; | |||
| var hasOwnProperty = Object.prototype.hasOwnProperty; | |||
| var propIsEnumerable = Object.prototype.propertyIsEnumerable; | |||
| function toObject(val) { | |||
| if (val === null || val === undefined) { | |||
| throw new TypeError('Object.assign cannot be called with null or undefined'); | |||
| } | |||
| return Object(val); | |||
| } | |||
| function shouldUseNative() { | |||
| try { | |||
| if (!Object.assign) { | |||
| return false; | |||
| } | |||
| // Detect buggy property enumeration order in older V8 versions. | |||
| // https://bugs.chromium.org/p/v8/issues/detail?id=4118 | |||
| var test1 = new String('abc'); // eslint-disable-line no-new-wrappers | |||
| test1[5] = 'de'; | |||
| if (Object.getOwnPropertyNames(test1)[0] === '5') { | |||
| return false; | |||
| } | |||
| // https://bugs.chromium.org/p/v8/issues/detail?id=3056 | |||
| var test2 = {}; | |||
| for (var i = 0; i < 10; i++) { | |||
| test2['_' + String.fromCharCode(i)] = i; | |||
| } | |||
| var order2 = Object.getOwnPropertyNames(test2).map(function (n) { | |||
| return test2[n]; | |||
| }); | |||
| if (order2.join('') !== '0123456789') { | |||
| return false; | |||
| } | |||
| // https://bugs.chromium.org/p/v8/issues/detail?id=3056 | |||
| var test3 = {}; | |||
| 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { | |||
| test3[letter] = letter; | |||
| }); | |||
| if (Object.keys(Object.assign({}, test3)).join('') !== | |||
| 'abcdefghijklmnopqrst') { | |||
| return false; | |||
| } | |||
| return true; | |||
| } catch (err) { | |||
| // We don't expect any of the above to throw, but better to be safe. | |||
| return false; | |||
| } | |||
| } | |||
| module.exports = shouldUseNative() ? Object.assign : function (target, source) { | |||
| var from; | |||
| var to = toObject(target); | |||
| var symbols; | |||
| for (var s = 1; s < arguments.length; s++) { | |||
| from = Object(arguments[s]); | |||
| for (var key in from) { | |||
| if (hasOwnProperty.call(from, key)) { | |||
| to[key] = from[key]; | |||
| } | |||
| } | |||
| if (getOwnPropertySymbols) { | |||
| symbols = getOwnPropertySymbols(from); | |||
| for (var i = 0; i < symbols.length; i++) { | |||
| if (propIsEnumerable.call(from, symbols[i])) { | |||
| to[symbols[i]] = from[symbols[i]]; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return to; | |||
| }; | |||
| @@ -0,0 +1,21 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in | |||
| all copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| THE SOFTWARE. | |||
| @@ -0,0 +1,42 @@ | |||
| { | |||
| "name": "object-assign", | |||
| "version": "4.1.1", | |||
| "description": "ES2015 `Object.assign()` ponyfill", | |||
| "license": "MIT", | |||
| "repository": "sindresorhus/object-assign", | |||
| "author": { | |||
| "name": "Sindre Sorhus", | |||
| "email": "sindresorhus@gmail.com", | |||
| "url": "sindresorhus.com" | |||
| }, | |||
| "engines": { | |||
| "node": ">=0.10.0" | |||
| }, | |||
| "scripts": { | |||
| "test": "xo && ava", | |||
| "bench": "matcha bench.js" | |||
| }, | |||
| "files": [ | |||
| "index.js" | |||
| ], | |||
| "keywords": [ | |||
| "object", | |||
| "assign", | |||
| "extend", | |||
| "properties", | |||
| "es2015", | |||
| "ecmascript", | |||
| "harmony", | |||
| "ponyfill", | |||
| "prollyfill", | |||
| "polyfill", | |||
| "shim", | |||
| "browser" | |||
| ], | |||
| "devDependencies": { | |||
| "ava": "^0.16.0", | |||
| "lodash": "^4.16.4", | |||
| "matcha": "^0.7.0", | |||
| "xo": "^0.16.0" | |||
| } | |||
| } | |||
| @@ -0,0 +1,61 @@ | |||
| # object-assign [](https://travis-ci.org/sindresorhus/object-assign) | |||
| > ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com) | |||
| ## Use the built-in | |||
| Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari), | |||
| support `Object.assign()` :tada:. If you target only those environments, then by all | |||
| means, use `Object.assign()` instead of this package. | |||
| ## Install | |||
| ``` | |||
| $ npm install --save object-assign | |||
| ``` | |||
| ## Usage | |||
| ```js | |||
| const objectAssign = require('object-assign'); | |||
| objectAssign({foo: 0}, {bar: 1}); | |||
| //=> {foo: 0, bar: 1} | |||
| // multiple sources | |||
| objectAssign({foo: 0}, {bar: 1}, {baz: 2}); | |||
| //=> {foo: 0, bar: 1, baz: 2} | |||
| // overwrites equal keys | |||
| objectAssign({foo: 0}, {foo: 1}, {foo: 2}); | |||
| //=> {foo: 2} | |||
| // ignores null and undefined sources | |||
| objectAssign({foo: 0}, null, {bar: 1}, undefined); | |||
| //=> {foo: 0, bar: 1} | |||
| ``` | |||
| ## API | |||
| ### objectAssign(target, [source, ...]) | |||
| Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones. | |||
| ## Resources | |||
| - [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign) | |||
| ## Related | |||
| - [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()` | |||
| ## License | |||
| MIT © [Sindre Sorhus](https://sindresorhus.com) | |||
| @@ -0,0 +1,21 @@ | |||
| MIT License | |||
| Copyright (c) 2013-present, Facebook, Inc. | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in all | |||
| copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| SOFTWARE. | |||
| @@ -0,0 +1,302 @@ | |||
| # prop-types [](https://travis-ci.org/facebook/prop-types) | |||
| Runtime type checking for React props and similar objects. | |||
| You can use prop-types to document the intended types of properties passed to | |||
| components. React (and potentially other libraries—see the `checkPropTypes()` | |||
| reference below) will check props passed to your components against those | |||
| definitions, and warn in development if they don’t match. | |||
| ## Installation | |||
| ```shell | |||
| npm install --save prop-types | |||
| ``` | |||
| ## Importing | |||
| ```js | |||
| import PropTypes from 'prop-types'; // ES6 | |||
| var PropTypes = require('prop-types'); // ES5 with npm | |||
| ``` | |||
| ### CDN | |||
| If you prefer to exclude `prop-types` from your application and use it | |||
| globally via `window.PropTypes`, the `prop-types` package provides | |||
| single-file distributions, which are hosted on the following CDNs: | |||
| * [**unpkg**](https://unpkg.com/prop-types/) | |||
| ```html | |||
| <!-- development version --> | |||
| <script src="https://unpkg.com/prop-types@15.6/prop-types.js"></script> | |||
| <!-- production version --> | |||
| <script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script> | |||
| ``` | |||
| * [**cdnjs**](https://cdnjs.com/libraries/prop-types) | |||
| ```html | |||
| <!-- development version --> | |||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script> | |||
| <!-- production version --> | |||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.min.js"></script> | |||
| ``` | |||
| To load a specific version of `prop-types` replace `15.6.0` with the version number. | |||
| ## Usage | |||
| PropTypes was originally exposed as part of the React core module, and is | |||
| commonly used with React components. | |||
| Here is an example of using PropTypes with a React component, which also | |||
| documents the different validators provided: | |||
| ```js | |||
| import React from 'react'; | |||
| import PropTypes from 'prop-types'; | |||
| class MyComponent extends React.Component { | |||
| render() { | |||
| // ... do things with the props | |||
| } | |||
| } | |||
| MyComponent.propTypes = { | |||
| // You can declare that a prop is a specific JS primitive. By default, these | |||
| // are all optional. | |||
| optionalArray: PropTypes.array, | |||
| optionalBigInt: PropTypes.bigint, | |||
| optionalBool: PropTypes.bool, | |||
| optionalFunc: PropTypes.func, | |||
| optionalNumber: PropTypes.number, | |||
| optionalObject: PropTypes.object, | |||
| optionalString: PropTypes.string, | |||
| optionalSymbol: PropTypes.symbol, | |||
| // Anything that can be rendered: numbers, strings, elements or an array | |||
| // (or fragment) containing these types. | |||
| // see https://reactjs.org/docs/rendering-elements.html for more info | |||
| optionalNode: PropTypes.node, | |||
| // A React element (ie. <MyComponent />). | |||
| optionalElement: PropTypes.element, | |||
| // A React element type (eg. MyComponent). | |||
| // a function, string, or "element-like" object (eg. React.Fragment, Suspense, etc.) | |||
| // see https://github.com/facebook/react/blob/HEAD/packages/shared/isValidElementType.js | |||
| optionalElementType: PropTypes.elementType, | |||
| // You can also declare that a prop is an instance of a class. This uses | |||
| // JS's instanceof operator. | |||
| optionalMessage: PropTypes.instanceOf(Message), | |||
| // You can ensure that your prop is limited to specific values by treating | |||
| // it as an enum. | |||
| optionalEnum: PropTypes.oneOf(['News', 'Photos']), | |||
| // An object that could be one of many types | |||
| optionalUnion: PropTypes.oneOfType([ | |||
| PropTypes.string, | |||
| PropTypes.number, | |||
| PropTypes.instanceOf(Message) | |||
| ]), | |||
| // An array of a certain type | |||
| optionalArrayOf: PropTypes.arrayOf(PropTypes.number), | |||
| // An object with property values of a certain type | |||
| optionalObjectOf: PropTypes.objectOf(PropTypes.number), | |||
| // You can chain any of the above with `isRequired` to make sure a warning | |||
| // is shown if the prop isn't provided. | |||
| // An object taking on a particular shape | |||
| optionalObjectWithShape: PropTypes.shape({ | |||
| optionalProperty: PropTypes.string, | |||
| requiredProperty: PropTypes.number.isRequired | |||
| }), | |||
| // An object with warnings on extra properties | |||
| optionalObjectWithStrictShape: PropTypes.exact({ | |||
| optionalProperty: PropTypes.string, | |||
| requiredProperty: PropTypes.number.isRequired | |||
| }), | |||
| requiredFunc: PropTypes.func.isRequired, | |||
| // A value of any data type | |||
| requiredAny: PropTypes.any.isRequired, | |||
| // You can also specify a custom validator. It should return an Error | |||
| // object if the validation fails. Don't `console.warn` or throw, as this | |||
| // won't work inside `oneOfType`. | |||
| customProp: function(props, propName, componentName) { | |||
| if (!/matchme/.test(props[propName])) { | |||
| return new Error( | |||
| 'Invalid prop `' + propName + '` supplied to' + | |||
| ' `' + componentName + '`. Validation failed.' | |||
| ); | |||
| } | |||
| }, | |||
| // You can also supply a custom validator to `arrayOf` and `objectOf`. | |||
| // It should return an Error object if the validation fails. The validator | |||
| // will be called for each key in the array or object. The first two | |||
| // arguments of the validator are the array or object itself, and the | |||
| // current item's key. | |||
| customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) { | |||
| if (!/matchme/.test(propValue[key])) { | |||
| return new Error( | |||
| 'Invalid prop `' + propFullName + '` supplied to' + | |||
| ' `' + componentName + '`. Validation failed.' | |||
| ); | |||
| } | |||
| }) | |||
| }; | |||
| ``` | |||
| Refer to the [React documentation](https://facebook.github.io/react/docs/typechecking-with-proptypes.html) for more information. | |||
| ## Migrating from React.PropTypes | |||
| Check out [Migrating from React.PropTypes](https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html#migrating-from-react.proptypes) for details on how to migrate to `prop-types` from `React.PropTypes`. | |||
| Note that this blog posts **mentions a codemod script that performs the conversion automatically**. | |||
| There are also important notes below. | |||
| ## How to Depend on This Package? | |||
| For apps, we recommend putting it in `dependencies` with a caret range. | |||
| For example: | |||
| ```js | |||
| "dependencies": { | |||
| "prop-types": "^15.5.7" | |||
| } | |||
| ``` | |||
| For libraries, we *also* recommend leaving it in `dependencies`: | |||
| ```js | |||
| "dependencies": { | |||
| "prop-types": "^15.5.7" | |||
| }, | |||
| "peerDependencies": { | |||
| "react": "^15.5.0" | |||
| } | |||
| ``` | |||
| **Note:** there are known issues in versions before 15.5.7 so we recommend using it as the minimal version. | |||
| Make sure that the version range uses a caret (`^`) and thus is broad enough for npm to efficiently deduplicate packages. | |||
| For UMD bundles of your components, make sure you **don’t** include `PropTypes` in the build. Usually this is done by marking it as an external (the specifics depend on your bundler), just like you do with React. | |||
| ## Compatibility | |||
| ### React 0.14 | |||
| This package is compatible with **React 0.14.9**. Compared to 0.14.8 (which was released in March of 2016), there are no other changes in 0.14.9, so it should be a painless upgrade. | |||
| ```shell | |||
| # ATTENTION: Only run this if you still use React 0.14! | |||
| npm install --save react@^0.14.9 react-dom@^0.14.9 | |||
| ``` | |||
| ### React 15+ | |||
| This package is compatible with **React 15.3.0** and higher. | |||
| ``` | |||
| npm install --save react@^15.3.0 react-dom@^15.3.0 | |||
| ``` | |||
| ### What happens on other React versions? | |||
| It outputs warnings with the message below even though the developer doesn’t do anything wrong. Unfortunately there is no solution for this other than updating React to either 15.3.0 or higher, or 0.14.9 if you’re using React 0.14. | |||
| ## Difference from `React.PropTypes`: Don’t Call Validator Functions | |||
| First of all, **which version of React are you using**? You might be seeing this message because a component library has updated to use `prop-types` package, but your version of React is incompatible with it. See the [above section](#compatibility) for more details. | |||
| Are you using either React 0.14.9 or a version higher than React 15.3.0? Read on. | |||
| When you migrate components to use the standalone `prop-types`, **all validator functions will start throwing an error if you call them directly**. This makes sure that nobody relies on them in production code, and it is safe to strip their implementations to optimize the bundle size. | |||
| Code like this is still fine: | |||
| ```js | |||
| MyComponent.propTypes = { | |||
| myProp: PropTypes.bool | |||
| }; | |||
| ``` | |||
| However, code like this will not work with the `prop-types` package: | |||
| ```js | |||
| // Will not work with `prop-types` package! | |||
| var errorOrNull = PropTypes.bool(42, 'myProp', 'MyComponent', 'prop'); | |||
| ``` | |||
| It will throw an error: | |||
| ``` | |||
| Calling PropTypes validators directly is not supported by the `prop-types` package. | |||
| Use PropTypes.checkPropTypes() to call them. | |||
| ``` | |||
| (If you see **a warning** rather than an error with this message, please check the [above section about compatibility](#compatibility).) | |||
| This is new behavior, and you will only encounter it when you migrate from `React.PropTypes` to the `prop-types` package. For the vast majority of components, this doesn’t matter, and if you didn’t see [this warning](https://facebook.github.io/react/warnings/dont-call-proptypes.html) in your components, your code is safe to migrate. This is not a breaking change in React because you are only opting into this change for a component by explicitly changing your imports to use `prop-types`. If you temporarily need the old behavior, you can keep using `React.PropTypes` until React 16. | |||
| **If you absolutely need to trigger the validation manually**, call `PropTypes.checkPropTypes()`. Unlike the validators themselves, this function is safe to call in production, as it will be replaced by an empty function: | |||
| ```js | |||
| // Works with standalone PropTypes | |||
| PropTypes.checkPropTypes(MyComponent.propTypes, props, 'prop', 'MyComponent'); | |||
| ``` | |||
| See below for more info. | |||
| **If you DO want to use validation in production**, you can choose to use the **development version** by importing/requiring `prop-types/prop-types` instead of `prop-types`. | |||
| **You might also see this error** if you’re calling a `PropTypes` validator from your own custom `PropTypes` validator. In this case, the fix is to make sure that you are passing *all* of the arguments to the inner function. There is a more in-depth explanation of how to fix it [on this page](https://facebook.github.io/react/warnings/dont-call-proptypes.html#fixing-the-false-positive-in-third-party-proptypes). Alternatively, you can temporarily keep using `React.PropTypes` until React 16, as it would still only warn in this case. | |||
| If you use a bundler like Browserify or Webpack, don’t forget to [follow these instructions](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build) to correctly bundle your application in development or production mode. Otherwise you’ll ship unnecessary code to your users. | |||
| ## PropTypes.checkPropTypes | |||
| React will automatically check the propTypes you set on the component, but if | |||
| you are using PropTypes without React then you may want to manually call | |||
| `PropTypes.checkPropTypes`, like so: | |||
| ```js | |||
| const myPropTypes = { | |||
| name: PropTypes.string, | |||
| age: PropTypes.number, | |||
| // ... define your prop validations | |||
| }; | |||
| const props = { | |||
| name: 'hello', // is valid | |||
| age: 'world', // not valid | |||
| }; | |||
| // Let's say your component is called 'MyComponent' | |||
| // Works with standalone PropTypes | |||
| PropTypes.checkPropTypes(myPropTypes, props, 'prop', 'MyComponent'); | |||
| // This will warn as follows: | |||
| // Warning: Failed prop type: Invalid prop `age` of type `string` supplied to | |||
| // `MyComponent`, expected `number`. | |||
| ``` | |||
| ## PropTypes.resetWarningCache() | |||
| `PropTypes.checkPropTypes(...)` only `console.error`s a given message once. To reset the error warning cache in tests, call `PropTypes.resetWarningCache()` | |||
| ### License | |||
| prop-types is [MIT licensed](./LICENSE). | |||
| @@ -0,0 +1,103 @@ | |||
| /** | |||
| * Copyright (c) 2013-present, Facebook, Inc. | |||
| * | |||
| * This source code is licensed under the MIT license found in the | |||
| * LICENSE file in the root directory of this source tree. | |||
| */ | |||
| 'use strict'; | |||
| var printWarning = function() {}; | |||
| if (process.env.NODE_ENV !== 'production') { | |||
| var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); | |||
| var loggedTypeFailures = {}; | |||
| var has = require('./lib/has'); | |||
| printWarning = function(text) { | |||
| var message = 'Warning: ' + text; | |||
| if (typeof console !== 'undefined') { | |||
| console.error(message); | |||
| } | |||
| try { | |||
| // --- Welcome to debugging React --- | |||
| // This error was thrown as a convenience so that you can use this stack | |||
| // to find the callsite that caused this warning to fire. | |||
| throw new Error(message); | |||
| } catch (x) { /**/ } | |||
| }; | |||
| } | |||
| /** | |||
| * Assert that the values match with the type specs. | |||
| * Error messages are memorized and will only be shown once. | |||
| * | |||
| * @param {object} typeSpecs Map of name to a ReactPropType | |||
| * @param {object} values Runtime values that need to be type-checked | |||
| * @param {string} location e.g. "prop", "context", "child context" | |||
| * @param {string} componentName Name of the component for error messages. | |||
| * @param {?Function} getStack Returns the component stack. | |||
| * @private | |||
| */ | |||
| function checkPropTypes(typeSpecs, values, location, componentName, getStack) { | |||
| if (process.env.NODE_ENV !== 'production') { | |||
| for (var typeSpecName in typeSpecs) { | |||
| if (has(typeSpecs, typeSpecName)) { | |||
| var error; | |||
| // Prop type validation may throw. In case they do, we don't want to | |||
| // fail the render phase where it didn't fail before. So we log it. | |||
| // After these have been cleaned up, we'll let them throw. | |||
| try { | |||
| // This is intentionally an invariant that gets caught. It's the same | |||
| // behavior as without this statement except with a better message. | |||
| if (typeof typeSpecs[typeSpecName] !== 'function') { | |||
| var err = Error( | |||
| (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + | |||
| 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + | |||
| 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.' | |||
| ); | |||
| err.name = 'Invariant Violation'; | |||
| throw err; | |||
| } | |||
| error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); | |||
| } catch (ex) { | |||
| error = ex; | |||
| } | |||
| if (error && !(error instanceof Error)) { | |||
| printWarning( | |||
| (componentName || 'React class') + ': type specification of ' + | |||
| location + ' `' + typeSpecName + '` is invalid; the type checker ' + | |||
| 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' + | |||
| 'You may have forgotten to pass an argument to the type checker ' + | |||
| 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + | |||
| 'shape all require an argument).' | |||
| ); | |||
| } | |||
| if (error instanceof Error && !(error.message in loggedTypeFailures)) { | |||
| // Only monitor this failure once because there tends to be a lot of the | |||
| // same error. | |||
| loggedTypeFailures[error.message] = true; | |||
| var stack = getStack ? getStack() : ''; | |||
| printWarning( | |||
| 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '') | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Resets warning cache when testing. | |||
| * | |||
| * @private | |||
| */ | |||
| checkPropTypes.resetWarningCache = function() { | |||
| if (process.env.NODE_ENV !== 'production') { | |||
| loggedTypeFailures = {}; | |||
| } | |||
| } | |||
| module.exports = checkPropTypes; | |||
| @@ -0,0 +1,19 @@ | |||
| /** | |||
| * Copyright (c) 2013-present, Facebook, Inc. | |||
| * | |||
| * This source code is licensed under the MIT license found in the | |||
| * LICENSE file in the root directory of this source tree. | |||
| */ | |||
| 'use strict'; | |||
| // React 15.5 references this module, and assumes PropTypes are still callable in production. | |||
| // Therefore we re-export development-only version with all the PropTypes checks here. | |||
| // However if one is migrating to the `prop-types` npm library, they will go through the | |||
| // `index.js` entry point, and it will branch depending on the environment. | |||
| var factory = require('./factoryWithTypeCheckers'); | |||
| module.exports = function(isValidElement) { | |||
| // It is still allowed in 15.5. | |||
| var throwOnDirectAccess = false; | |||
| return factory(isValidElement, throwOnDirectAccess); | |||
| }; | |||
| @@ -0,0 +1,65 @@ | |||
| /** | |||
| * Copyright (c) 2013-present, Facebook, Inc. | |||
| * | |||
| * This source code is licensed under the MIT license found in the | |||
| * LICENSE file in the root directory of this source tree. | |||
| */ | |||
| 'use strict'; | |||
| var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); | |||
| function emptyFunction() {} | |||
| function emptyFunctionWithReset() {} | |||
| emptyFunctionWithReset.resetWarningCache = emptyFunction; | |||
| module.exports = function() { | |||
| function shim(props, propName, componentName, location, propFullName, secret) { | |||
| if (secret === ReactPropTypesSecret) { | |||
| // It is still safe when called from React. | |||
| return; | |||
| } | |||
| var err = new Error( | |||
| 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + | |||
| 'Use PropTypes.checkPropTypes() to call them. ' + | |||
| 'Read more at http://fb.me/use-check-prop-types' | |||
| ); | |||
| err.name = 'Invariant Violation'; | |||
| throw err; | |||
| }; | |||
| shim.isRequired = shim; | |||
| function getShim() { | |||
| return shim; | |||
| }; | |||
| // Important! | |||
| // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. | |||
| var ReactPropTypes = { | |||
| array: shim, | |||
| bigint: shim, | |||
| bool: shim, | |||
| func: shim, | |||
| number: shim, | |||
| object: shim, | |||
| string: shim, | |||
| symbol: shim, | |||
| any: shim, | |||
| arrayOf: getShim, | |||
| element: shim, | |||
| elementType: shim, | |||
| instanceOf: getShim, | |||
| node: shim, | |||
| objectOf: getShim, | |||
| oneOf: getShim, | |||
| oneOfType: getShim, | |||
| shape: getShim, | |||
| exact: getShim, | |||
| checkPropTypes: emptyFunctionWithReset, | |||
| resetWarningCache: emptyFunction | |||
| }; | |||
| ReactPropTypes.PropTypes = ReactPropTypes; | |||
| return ReactPropTypes; | |||
| }; | |||
| @@ -0,0 +1,610 @@ | |||
| /** | |||
| * Copyright (c) 2013-present, Facebook, Inc. | |||
| * | |||
| * This source code is licensed under the MIT license found in the | |||
| * LICENSE file in the root directory of this source tree. | |||
| */ | |||
| 'use strict'; | |||
| var ReactIs = require('react-is'); | |||
| var assign = require('object-assign'); | |||
| var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); | |||
| var has = require('./lib/has'); | |||
| var checkPropTypes = require('./checkPropTypes'); | |||
| var printWarning = function() {}; | |||
| if (process.env.NODE_ENV !== 'production') { | |||
| printWarning = function(text) { | |||
| var message = 'Warning: ' + text; | |||
| if (typeof console !== 'undefined') { | |||
| console.error(message); | |||
| } | |||
| try { | |||
| // --- Welcome to debugging React --- | |||
| // This error was thrown as a convenience so that you can use this stack | |||
| // to find the callsite that caused this warning to fire. | |||
| throw new Error(message); | |||
| } catch (x) {} | |||
| }; | |||
| } | |||
| function emptyFunctionThatReturnsNull() { | |||
| return null; | |||
| } | |||
| module.exports = function(isValidElement, throwOnDirectAccess) { | |||
| /* global Symbol */ | |||
| var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; | |||
| var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. | |||
| /** | |||
| * Returns the iterator method function contained on the iterable object. | |||
| * | |||
| * Be sure to invoke the function with the iterable as context: | |||
| * | |||
| * var iteratorFn = getIteratorFn(myIterable); | |||
| * if (iteratorFn) { | |||
| * var iterator = iteratorFn.call(myIterable); | |||
| * ... | |||
| * } | |||
| * | |||
| * @param {?object} maybeIterable | |||
| * @return {?function} | |||
| */ | |||
| function getIteratorFn(maybeIterable) { | |||
| var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); | |||
| if (typeof iteratorFn === 'function') { | |||
| return iteratorFn; | |||
| } | |||
| } | |||
| /** | |||
| * Collection of methods that allow declaration and validation of props that are | |||
| * supplied to React components. Example usage: | |||
| * | |||
| * var Props = require('ReactPropTypes'); | |||
| * var MyArticle = React.createClass({ | |||
| * propTypes: { | |||
| * // An optional string prop named "description". | |||
| * description: Props.string, | |||
| * | |||
| * // A required enum prop named "category". | |||
| * category: Props.oneOf(['News','Photos']).isRequired, | |||
| * | |||
| * // A prop named "dialog" that requires an instance of Dialog. | |||
| * dialog: Props.instanceOf(Dialog).isRequired | |||
| * }, | |||
| * render: function() { ... } | |||
| * }); | |||
| * | |||
| * A more formal specification of how these methods are used: | |||
| * | |||
| * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) | |||
| * decl := ReactPropTypes.{type}(.isRequired)? | |||
| * | |||
| * Each and every declaration produces a function with the same signature. This | |||
| * allows the creation of custom validation functions. For example: | |||
| * | |||
| * var MyLink = React.createClass({ | |||
| * propTypes: { | |||
| * // An optional string or URI prop named "href". | |||
| * href: function(props, propName, componentName) { | |||
| * var propValue = props[propName]; | |||
| * if (propValue != null && typeof propValue !== 'string' && | |||
| * !(propValue instanceof URI)) { | |||
| * return new Error( | |||
| * 'Expected a string or an URI for ' + propName + ' in ' + | |||
| * componentName | |||
| * ); | |||
| * } | |||
| * } | |||
| * }, | |||
| * render: function() {...} | |||
| * }); | |||
| * | |||
| * @internal | |||
| */ | |||
| var ANONYMOUS = '<<anonymous>>'; | |||
| // Important! | |||
| // Keep this list in sync with production version in `./factoryWithThrowingShims.js`. | |||
| var ReactPropTypes = { | |||
| array: createPrimitiveTypeChecker('array'), | |||
| bigint: createPrimitiveTypeChecker('bigint'), | |||
| bool: createPrimitiveTypeChecker('boolean'), | |||
| func: createPrimitiveTypeChecker('function'), | |||
| number: createPrimitiveTypeChecker('number'), | |||
| object: createPrimitiveTypeChecker('object'), | |||
| string: createPrimitiveTypeChecker('string'), | |||
| symbol: createPrimitiveTypeChecker('symbol'), | |||
| any: createAnyTypeChecker(), | |||
| arrayOf: createArrayOfTypeChecker, | |||
| element: createElementTypeChecker(), | |||
| elementType: createElementTypeTypeChecker(), | |||
| instanceOf: createInstanceTypeChecker, | |||
| node: createNodeChecker(), | |||
| objectOf: createObjectOfTypeChecker, | |||
| oneOf: createEnumTypeChecker, | |||
| oneOfType: createUnionTypeChecker, | |||
| shape: createShapeTypeChecker, | |||
| exact: createStrictShapeTypeChecker, | |||
| }; | |||
| /** | |||
| * inlined Object.is polyfill to avoid requiring consumers ship their own | |||
| * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is | |||
| */ | |||
| /*eslint-disable no-self-compare*/ | |||
| function is(x, y) { | |||
| // SameValue algorithm | |||
| if (x === y) { | |||
| // Steps 1-5, 7-10 | |||
| // Steps 6.b-6.e: +0 != -0 | |||
| return x !== 0 || 1 / x === 1 / y; | |||
| } else { | |||
| // Step 6.a: NaN == NaN | |||
| return x !== x && y !== y; | |||
| } | |||
| } | |||
| /*eslint-enable no-self-compare*/ | |||
| /** | |||
| * We use an Error-like object for backward compatibility as people may call | |||
| * PropTypes directly and inspect their output. However, we don't use real | |||
| * Errors anymore. We don't inspect their stack anyway, and creating them | |||
| * is prohibitively expensive if they are created too often, such as what | |||
| * happens in oneOfType() for any type before the one that matched. | |||
| */ | |||
| function PropTypeError(message, data) { | |||
| this.message = message; | |||
| this.data = data && typeof data === 'object' ? data: {}; | |||
| this.stack = ''; | |||
| } | |||
| // Make `instanceof Error` still work for returned errors. | |||
| PropTypeError.prototype = Error.prototype; | |||
| function createChainableTypeChecker(validate) { | |||
| if (process.env.NODE_ENV !== 'production') { | |||
| var manualPropTypeCallCache = {}; | |||
| var manualPropTypeWarningCount = 0; | |||
| } | |||
| function checkType(isRequired, props, propName, componentName, location, propFullName, secret) { | |||
| componentName = componentName || ANONYMOUS; | |||
| propFullName = propFullName || propName; | |||
| if (secret !== ReactPropTypesSecret) { | |||
| if (throwOnDirectAccess) { | |||
| // New behavior only for users of `prop-types` package | |||
| var err = new Error( | |||
| 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + | |||
| 'Use `PropTypes.checkPropTypes()` to call them. ' + | |||
| 'Read more at http://fb.me/use-check-prop-types' | |||
| ); | |||
| err.name = 'Invariant Violation'; | |||
| throw err; | |||
| } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') { | |||
| // Old behavior for people using React.PropTypes | |||
| var cacheKey = componentName + ':' + propName; | |||
| if ( | |||
| !manualPropTypeCallCache[cacheKey] && | |||
| // Avoid spamming the console because they are often not actionable except for lib authors | |||
| manualPropTypeWarningCount < 3 | |||
| ) { | |||
| printWarning( | |||
| 'You are manually calling a React.PropTypes validation ' + | |||
| 'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' + | |||
| 'and will throw in the standalone `prop-types` package. ' + | |||
| 'You may be seeing this warning due to a third-party PropTypes ' + | |||
| 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.' | |||
| ); | |||
| manualPropTypeCallCache[cacheKey] = true; | |||
| manualPropTypeWarningCount++; | |||
| } | |||
| } | |||
| } | |||
| if (props[propName] == null) { | |||
| if (isRequired) { | |||
| if (props[propName] === null) { | |||
| return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.')); | |||
| } | |||
| return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.')); | |||
| } | |||
| return null; | |||
| } else { | |||
| return validate(props, propName, componentName, location, propFullName); | |||
| } | |||
| } | |||
| var chainedCheckType = checkType.bind(null, false); | |||
| chainedCheckType.isRequired = checkType.bind(null, true); | |||
| return chainedCheckType; | |||
| } | |||
| function createPrimitiveTypeChecker(expectedType) { | |||
| function validate(props, propName, componentName, location, propFullName, secret) { | |||
| var propValue = props[propName]; | |||
| var propType = getPropType(propValue); | |||
| if (propType !== expectedType) { | |||
| // `propValue` being instance of, say, date/regexp, pass the 'object' | |||
| // check, but we can offer a more precise error message here rather than | |||
| // 'of type `object`'. | |||
| var preciseType = getPreciseType(propValue); | |||
| return new PropTypeError( | |||
| 'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'), | |||
| {expectedType: expectedType} | |||
| ); | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createAnyTypeChecker() { | |||
| return createChainableTypeChecker(emptyFunctionThatReturnsNull); | |||
| } | |||
| function createArrayOfTypeChecker(typeChecker) { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| if (typeof typeChecker !== 'function') { | |||
| return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.'); | |||
| } | |||
| var propValue = props[propName]; | |||
| if (!Array.isArray(propValue)) { | |||
| var propType = getPropType(propValue); | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.')); | |||
| } | |||
| for (var i = 0; i < propValue.length; i++) { | |||
| var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret); | |||
| if (error instanceof Error) { | |||
| return error; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createElementTypeChecker() { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| var propValue = props[propName]; | |||
| if (!isValidElement(propValue)) { | |||
| var propType = getPropType(propValue); | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.')); | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createElementTypeTypeChecker() { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| var propValue = props[propName]; | |||
| if (!ReactIs.isValidElementType(propValue)) { | |||
| var propType = getPropType(propValue); | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.')); | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createInstanceTypeChecker(expectedClass) { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| if (!(props[propName] instanceof expectedClass)) { | |||
| var expectedClassName = expectedClass.name || ANONYMOUS; | |||
| var actualClassName = getClassName(props[propName]); | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.')); | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createEnumTypeChecker(expectedValues) { | |||
| if (!Array.isArray(expectedValues)) { | |||
| if (process.env.NODE_ENV !== 'production') { | |||
| if (arguments.length > 1) { | |||
| printWarning( | |||
| 'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' + | |||
| 'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).' | |||
| ); | |||
| } else { | |||
| printWarning('Invalid argument supplied to oneOf, expected an array.'); | |||
| } | |||
| } | |||
| return emptyFunctionThatReturnsNull; | |||
| } | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| var propValue = props[propName]; | |||
| for (var i = 0; i < expectedValues.length; i++) { | |||
| if (is(propValue, expectedValues[i])) { | |||
| return null; | |||
| } | |||
| } | |||
| var valuesString = JSON.stringify(expectedValues, function replacer(key, value) { | |||
| var type = getPreciseType(value); | |||
| if (type === 'symbol') { | |||
| return String(value); | |||
| } | |||
| return value; | |||
| }); | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createObjectOfTypeChecker(typeChecker) { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| if (typeof typeChecker !== 'function') { | |||
| return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); | |||
| } | |||
| var propValue = props[propName]; | |||
| var propType = getPropType(propValue); | |||
| if (propType !== 'object') { | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.')); | |||
| } | |||
| for (var key in propValue) { | |||
| if (has(propValue, key)) { | |||
| var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); | |||
| if (error instanceof Error) { | |||
| return error; | |||
| } | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createUnionTypeChecker(arrayOfTypeCheckers) { | |||
| if (!Array.isArray(arrayOfTypeCheckers)) { | |||
| process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; | |||
| return emptyFunctionThatReturnsNull; | |||
| } | |||
| for (var i = 0; i < arrayOfTypeCheckers.length; i++) { | |||
| var checker = arrayOfTypeCheckers[i]; | |||
| if (typeof checker !== 'function') { | |||
| printWarning( | |||
| 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' + | |||
| 'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.' | |||
| ); | |||
| return emptyFunctionThatReturnsNull; | |||
| } | |||
| } | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| var expectedTypes = []; | |||
| for (var i = 0; i < arrayOfTypeCheckers.length; i++) { | |||
| var checker = arrayOfTypeCheckers[i]; | |||
| var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret); | |||
| if (checkerResult == null) { | |||
| return null; | |||
| } | |||
| if (checkerResult.data && has(checkerResult.data, 'expectedType')) { | |||
| expectedTypes.push(checkerResult.data.expectedType); | |||
| } | |||
| } | |||
| var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': ''; | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.')); | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createNodeChecker() { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| if (!isNode(props[propName])) { | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function invalidValidatorError(componentName, location, propFullName, key, type) { | |||
| return new PropTypeError( | |||
| (componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' + | |||
| 'it must be a function, usually from the `prop-types` package, but received `' + type + '`.' | |||
| ); | |||
| } | |||
| function createShapeTypeChecker(shapeTypes) { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| var propValue = props[propName]; | |||
| var propType = getPropType(propValue); | |||
| if (propType !== 'object') { | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); | |||
| } | |||
| for (var key in shapeTypes) { | |||
| var checker = shapeTypes[key]; | |||
| if (typeof checker !== 'function') { | |||
| return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker)); | |||
| } | |||
| var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); | |||
| if (error) { | |||
| return error; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function createStrictShapeTypeChecker(shapeTypes) { | |||
| function validate(props, propName, componentName, location, propFullName) { | |||
| var propValue = props[propName]; | |||
| var propType = getPropType(propValue); | |||
| if (propType !== 'object') { | |||
| return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); | |||
| } | |||
| // We need to check all keys in case some are required but missing from props. | |||
| var allKeys = assign({}, props[propName], shapeTypes); | |||
| for (var key in allKeys) { | |||
| var checker = shapeTypes[key]; | |||
| if (has(shapeTypes, key) && typeof checker !== 'function') { | |||
| return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker)); | |||
| } | |||
| if (!checker) { | |||
| return new PropTypeError( | |||
| 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' + | |||
| '\nBad object: ' + JSON.stringify(props[propName], null, ' ') + | |||
| '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ') | |||
| ); | |||
| } | |||
| var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); | |||
| if (error) { | |||
| return error; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| return createChainableTypeChecker(validate); | |||
| } | |||
| function isNode(propValue) { | |||
| switch (typeof propValue) { | |||
| case 'number': | |||
| case 'string': | |||
| case 'undefined': | |||
| return true; | |||
| case 'boolean': | |||
| return !propValue; | |||
| case 'object': | |||
| if (Array.isArray(propValue)) { | |||
| return propValue.every(isNode); | |||
| } | |||
| if (propValue === null || isValidElement(propValue)) { | |||
| return true; | |||
| } | |||
| var iteratorFn = getIteratorFn(propValue); | |||
| if (iteratorFn) { | |||
| var iterator = iteratorFn.call(propValue); | |||
| var step; | |||
| if (iteratorFn !== propValue.entries) { | |||
| while (!(step = iterator.next()).done) { | |||
| if (!isNode(step.value)) { | |||
| return false; | |||
| } | |||
| } | |||
| } else { | |||
| // Iterator will provide entry [k,v] tuples rather than values. | |||
| while (!(step = iterator.next()).done) { | |||
| var entry = step.value; | |||
| if (entry) { | |||
| if (!isNode(entry[1])) { | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } else { | |||
| return false; | |||
| } | |||
| return true; | |||
| default: | |||
| return false; | |||
| } | |||
| } | |||
| function isSymbol(propType, propValue) { | |||
| // Native Symbol. | |||
| if (propType === 'symbol') { | |||
| return true; | |||
| } | |||
| // falsy value can't be a Symbol | |||
| if (!propValue) { | |||
| return false; | |||
| } | |||
| // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' | |||
| if (propValue['@@toStringTag'] === 'Symbol') { | |||
| return true; | |||
| } | |||
| // Fallback for non-spec compliant Symbols which are polyfilled. | |||
| if (typeof Symbol === 'function' && propValue instanceof Symbol) { | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| // Equivalent of `typeof` but with special handling for array and regexp. | |||
| function getPropType(propValue) { | |||
| var propType = typeof propValue; | |||
| if (Array.isArray(propValue)) { | |||
| return 'array'; | |||
| } | |||
| if (propValue instanceof RegExp) { | |||
| // Old webkits (at least until Android 4.0) return 'function' rather than | |||
| // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ | |||
| // passes PropTypes.object. | |||
| return 'object'; | |||
| } | |||
| if (isSymbol(propType, propValue)) { | |||
| return 'symbol'; | |||
| } | |||
| return propType; | |||
| } | |||
| // This handles more types than `getPropType`. Only used for error messages. | |||
| // See `createPrimitiveTypeChecker`. | |||
| function getPreciseType(propValue) { | |||
| if (typeof propValue === 'undefined' || propValue === null) { | |||
| return '' + propValue; | |||
| } | |||
| var propType = getPropType(propValue); | |||
| if (propType === 'object') { | |||
| if (propValue instanceof Date) { | |||
| return 'date'; | |||
| } else if (propValue instanceof RegExp) { | |||
| return 'regexp'; | |||
| } | |||
| } | |||
| return propType; | |||
| } | |||
| // Returns a string that is postfixed to a warning about an invalid type. | |||
| // For example, "undefined" or "of type array" | |||
| function getPostfixForTypeWarning(value) { | |||
| var type = getPreciseType(value); | |||
| switch (type) { | |||
| case 'array': | |||
| case 'object': | |||
| return 'an ' + type; | |||
| case 'boolean': | |||
| case 'date': | |||
| case 'regexp': | |||
| return 'a ' + type; | |||
| default: | |||
| return type; | |||
| } | |||
| } | |||
| // Returns class name of the object, if any. | |||
| function getClassName(propValue) { | |||
| if (!propValue.constructor || !propValue.constructor.name) { | |||
| return ANONYMOUS; | |||
| } | |||
| return propValue.constructor.name; | |||
| } | |||
| ReactPropTypes.checkPropTypes = checkPropTypes; | |||
| ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache; | |||
| ReactPropTypes.PropTypes = ReactPropTypes; | |||
| return ReactPropTypes; | |||
| }; | |||
| @@ -0,0 +1,19 @@ | |||
| /** | |||
| * Copyright (c) 2013-present, Facebook, Inc. | |||
| * | |||
| * This source code is licensed under the MIT license found in the | |||
| * LICENSE file in the root directory of this source tree. | |||
| */ | |||
| if (process.env.NODE_ENV !== 'production') { | |||
| var ReactIs = require('react-is'); | |||
| // By explicitly using `prop-types` you are opting into new development behavior. | |||
| // http://fb.me/prop-types-in-prod | |||
| var throwOnDirectAccess = true; | |||
| module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess); | |||
| } else { | |||
| // By explicitly using `prop-types` you are opting into new production behavior. | |||
| // http://fb.me/prop-types-in-prod | |||
| module.exports = require('./factoryWithThrowingShims')(); | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| /** | |||
| * Copyright (c) 2013-present, Facebook, Inc. | |||
| * | |||
| * This source code is licensed under the MIT license found in the | |||
| * LICENSE file in the root directory of this source tree. | |||
| */ | |||
| 'use strict'; | |||
| var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; | |||
| module.exports = ReactPropTypesSecret; | |||
| @@ -0,0 +1 @@ | |||
| module.exports = Function.call.bind(Object.prototype.hasOwnProperty); | |||
| @@ -0,0 +1,60 @@ | |||
| { | |||
| "name": "prop-types", | |||
| "version": "15.8.1", | |||
| "description": "Runtime type checking for React props and similar objects.", | |||
| "sideEffects": false, | |||
| "main": "index.js", | |||
| "license": "MIT", | |||
| "files": [ | |||
| "LICENSE", | |||
| "README.md", | |||
| "checkPropTypes.js", | |||
| "factory.js", | |||
| "factoryWithThrowingShims.js", | |||
| "factoryWithTypeCheckers.js", | |||
| "index.js", | |||
| "prop-types.js", | |||
| "prop-types.min.js", | |||
| "lib" | |||
| ], | |||
| "repository": "facebook/prop-types", | |||
| "keywords": [ | |||
| "react" | |||
| ], | |||
| "bugs": { | |||
| "url": "https://github.com/facebook/prop-types/issues" | |||
| }, | |||
| "homepage": "https://facebook.github.io/react/", | |||
| "dependencies": { | |||
| "loose-envify": "^1.4.0", | |||
| "object-assign": "^4.1.1", | |||
| "react-is": "^16.13.1" | |||
| }, | |||
| "scripts": { | |||
| "pretest": "npm run lint", | |||
| "lint": "eslint .", | |||
| "test": "npm run tests-only", | |||
| "tests-only": "jest", | |||
| "umd": "NODE_ENV=development browserify index.js -t loose-envify --standalone PropTypes -o prop-types.js", | |||
| "umd-min": "NODE_ENV=production browserify index.js -t loose-envify -t uglifyify --standalone PropTypes -p bundle-collapser/plugin -o | uglifyjs --compress unused,dead_code -o prop-types.min.js", | |||
| "build": "yarn umd && yarn umd-min", | |||
| "prepublish": "not-in-publish || yarn build" | |||
| }, | |||
| "devDependencies": { | |||
| "babel-jest": "^19.0.0", | |||
| "babel-preset-react": "^6.24.1", | |||
| "browserify": "^16.5.0", | |||
| "bundle-collapser": "^1.4.0", | |||
| "eslint": "^8.6.0", | |||
| "in-publish": "^2.0.1", | |||
| "jest": "^19.0.2", | |||
| "react": "^15.7.0", | |||
| "uglifyify": "^5.0.2", | |||
| "uglifyjs": "^2.4.11" | |||
| }, | |||
| "browserify": { | |||
| "transform": [ | |||
| "loose-envify" | |||
| ] | |||
| } | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| !function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).PropTypes=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var p="function"==typeof require&&require;if(!f&&p)return p(i,!0);if(u)return u(i,!0);throw(p=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",p}p=n[i]={exports:{}},e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){"use strict";var ReactPropTypesSecret=require(3);function emptyFunction(){}function emptyFunctionWithReset(){}emptyFunctionWithReset.resetWarningCache=emptyFunction,module.exports=function(){function e(e,t,n,r,o,c){if(c!==ReactPropTypesSecret){c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}var n={array:e.isRequired=e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:emptyFunctionWithReset,resetWarningCache:emptyFunction};return n.PropTypes=n}},{3:3}],2:[function(require,module,exports){module.exports=require(1)()},{1:1}],3:[function(require,module,exports){"use strict";module.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},{}]},{},[2])(2)}); | |||
| @@ -0,0 +1,6 @@ | |||
| node_modules | |||
| coverage | |||
| .nyc_output | |||
| dist | |||
| .github | |||
| .husky | |||
| @@ -0,0 +1,58 @@ | |||
| module.exports = { | |||
| parser: '@babel/eslint-parser', | |||
| extends: ['airbnb', 'prettier', 'plugin:jest/recommended'], | |||
| plugins: ['prettier', 'jest'], | |||
| env: { | |||
| browser: true | |||
| }, | |||
| rules: { | |||
| 'prettier/prettier': 'error', | |||
| 'react/no-find-dom-node': 'off', | |||
| 'arrow-body-style': 'off', | |||
| 'no-mixed-operators': 'off', | |||
| 'no-shadow': ['error', { allow: ['err', 'error'] }], | |||
| 'react/prefer-stateless-function': [ | |||
| 'error', | |||
| { ignorePureComponents: true } | |||
| ], | |||
| 'no-console': ['error', { allow: ['warn', 'error', 'info'] }], | |||
| 'no-underscore-dangle': 'off', | |||
| 'guard-for-in': 'off', | |||
| 'no-param-reassign': ['error', { props: false }], | |||
| 'jsx-a11y/label-has-associated-control': 'off', | |||
| 'jsx-a11y/control-has-associated-control': 'off', | |||
| 'react/jsx-curly-brace-presence': 'off', | |||
| 'react/jsx-one-expression-per-line': 'off', | |||
| 'react/jsx-props-no-spreading': 'off' | |||
| }, | |||
| overrides: [ | |||
| { | |||
| files: ['demo/**/*', 'src/components/*.js'], | |||
| rules: { | |||
| 'import/no-extraneous-dependencies': [ | |||
| 'error', | |||
| { devDependencies: true } | |||
| ], | |||
| 'import/no-named-as-default-member': 'off', | |||
| 'react/no-array-index-key': 'off', | |||
| 'react/jsx-no-bind': 'off', | |||
| 'react/prop-types': 'off' | |||
| } | |||
| }, | |||
| { | |||
| files: ['test/**/*'], | |||
| env: { | |||
| browser: true, | |||
| node: true, | |||
| 'jest/globals': true | |||
| }, | |||
| rules: { | |||
| 'import/no-extraneous-dependencies': [ | |||
| 'error', | |||
| { devDependencies: true } | |||
| ] | |||
| } | |||
| } | |||
| ] | |||
| }; | |||
| @@ -0,0 +1,23 @@ | |||
| name: Release | |||
| on: | |||
| push: | |||
| branches: | |||
| - master | |||
| jobs: | |||
| release: | |||
| name: Release | |||
| runs-on: ubuntu-18.04 | |||
| steps: | |||
| - name: Checkout | |||
| uses: actions/checkout@v1 | |||
| - name: Setup Node.js | |||
| uses: actions/setup-node@v1 | |||
| with: | |||
| node-version: 16 | |||
| - name: Install dependencies | |||
| run: npm ci | |||
| - name: Release | |||
| env: | |||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |||
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |||
| run: npx semantic-release | |||
| @@ -0,0 +1,26 @@ | |||
| name: Tests | |||
| on: | |||
| pull_request: | |||
| branches: [master] | |||
| jobs: | |||
| test: | |||
| runs-on: ubuntu-latest | |||
| env: | |||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |||
| steps: | |||
| - uses: actions/checkout@v2 | |||
| with: | |||
| fetch-depth: 0 | |||
| - name: Use Node.js 12 | |||
| uses: actions/setup-node@v1 | |||
| with: | |||
| node-version: 16 | |||
| - run: npm ci | |||
| - run: npm install react prop-types | |||
| - run: npm run build | |||
| - run: npm run lint | |||
| - run: npm test | |||
| - run: npm test:types | |||
| - uses: wagoid/commitlint-github-action@v1 | |||
| @@ -0,0 +1,4 @@ | |||
| #!/usr/bin/env sh | |||
| . "$(dirname -- "$0")/_/husky.sh" | |||
| npx commitlint -e | |||
| @@ -0,0 +1,4 @@ | |||
| #!/usr/bin/env sh | |||
| . "$(dirname -- "$0")/_/husky.sh" | |||
| npx lint-staged | |||