first commit
This commit is contained in:
127
components/common/Challanges.jsx
Normal file
127
components/common/Challanges.jsx
Normal file
@ -0,0 +1,127 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
export default function Challanges() {
|
||||
return (
|
||||
<div className="section tf-spacing-7">
|
||||
<div className="tf-container">
|
||||
<div className="heading-section text-center mb_87">
|
||||
<h2 className="split-text effect-right">
|
||||
Solving IT Challenges in Every Industry
|
||||
</h2>
|
||||
<p
|
||||
className="text_color-text-2 text-body-1 mt_20 wow animate__fadeInUp animate__animated"
|
||||
data-wow-delay="0s"
|
||||
>
|
||||
From an early stage start-up’s growth strategies to helping existing
|
||||
businesses, we have done it all!
|
||||
</p>
|
||||
</div>
|
||||
<div className="wrap-challenges-item">
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-1.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Agribussiness</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-2.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Advanced Manufacturing</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-3.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Automotive & Mobility</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-4.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Financial Services</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-5.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">
|
||||
Healthcare & Life Sciences
|
||||
</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-6.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">
|
||||
Ener & Natural Resources
|
||||
</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-7.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Media & Entertainment</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-8.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Telecommunication</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-9.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Social & Public Sector</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-10.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Technology</p>
|
||||
</a>
|
||||
<a href="#" className="challenges-item">
|
||||
<Image
|
||||
alt="challenges-item"
|
||||
src="/images/section/challenges-item-11.jpg"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
<p className="text-body-2 text_black">Forest Products</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
97
components/common/Contact.jsx
Normal file
97
components/common/Contact.jsx
Normal file
@ -0,0 +1,97 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
export default function Contact() {
|
||||
return (
|
||||
<div className="section-contact style-default position-relative">
|
||||
<div className="tf-container">
|
||||
<div className="row">
|
||||
<div className="col-lg-6">
|
||||
<div className="left">
|
||||
<div className="heading">
|
||||
<div className="h1 split-text split-lines-rotation-x">
|
||||
Success is a team play, right? Let's work together!
|
||||
</div>
|
||||
</div>
|
||||
<div className="bot">
|
||||
<div className="content">
|
||||
<h6 className="mb_5">+91 90954 50005</h6>
|
||||
<p className="text-body-2 text_mono-gray-6">
|
||||
Call us for urgent
|
||||
</p>
|
||||
</div>
|
||||
<Link href={`/contact-us`} className="tf-btn btn-primary2 h36">
|
||||
<span className="text-caption">Get Direction</span>
|
||||
<span className="bg-effect" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6">
|
||||
<form onSubmit={(e) => e.preventDefault()} className="form-contact">
|
||||
<fieldset>
|
||||
<label className="mb_15" htmlFor="name">
|
||||
Full Name*
|
||||
</label>
|
||||
<input type="text" placeholder="Full Name" id="name" required />
|
||||
</fieldset>
|
||||
<div className="grid-2 gap_24">
|
||||
<fieldset>
|
||||
<label className="mb_15" htmlFor="email">
|
||||
Email Address*
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
placeholder="Your email address*"
|
||||
id="email"
|
||||
required
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label className="mb_15" htmlFor="phone">
|
||||
Phone Number
|
||||
<span className="text_mono-gray-5">(Optional)</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Your phone number"
|
||||
id="phone"
|
||||
required
|
||||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
<fieldset className="">
|
||||
<label className="mb_15" htmlFor="message">
|
||||
Message
|
||||
</label>
|
||||
<textarea
|
||||
className="message"
|
||||
placeholder="Write your message here..."
|
||||
id="message"
|
||||
defaultValue={""}
|
||||
/>
|
||||
</fieldset>
|
||||
<a href="#" className="link attachment">
|
||||
<i className="icon-paperclip-solid" />
|
||||
Add an attachment
|
||||
</a>
|
||||
<button type="submit" className="tf-btn btn-primary2 mt_27">
|
||||
<span>Send Message</span>
|
||||
<span className="bg-effect" />
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="shape position-absolute">
|
||||
<Image
|
||||
alt="item"
|
||||
src="/images/item/shape-5.png"
|
||||
width={1105}
|
||||
height={720}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
206
components/common/Countdown.jsx
Normal file
206
components/common/Countdown.jsx
Normal file
@ -0,0 +1,206 @@
|
||||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
const CountdownTimer = ({ style = 1, targetDate = "2025-06-31T23:59:59" }) => {
|
||||
const [showTimer, setShowTimer] = useState(false);
|
||||
useEffect(() => {
|
||||
setShowTimer(true);
|
||||
}, []);
|
||||
|
||||
const calculateTimeLeft = () => {
|
||||
const difference = +new Date(targetDate) - +new Date();
|
||||
if (difference > 0) {
|
||||
return {
|
||||
days: Math.floor(difference / (1000 * 60 * 60 * 24)),
|
||||
hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
|
||||
minutes: Math.floor((difference / 1000 / 60) % 60),
|
||||
seconds: Math.floor((difference / 1000) % 60),
|
||||
};
|
||||
}
|
||||
return null; // Time is up
|
||||
};
|
||||
|
||||
const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setTimeLeft(calculateTimeLeft());
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timer); // Cleanup the timer on component unmount
|
||||
}, [targetDate]);
|
||||
|
||||
if (!timeLeft) {
|
||||
return <div>Time's up!</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{showTimer ? (
|
||||
<>
|
||||
{style == 1 && (
|
||||
<div aria-hidden="true" className="countdown__timer">
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--0 js-countdown__value--0">
|
||||
{timeLeft.days}
|
||||
</span>
|
||||
<span className="countdown__label">D :</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--1 js-countdown__value--1">
|
||||
{timeLeft.hours}
|
||||
</span>
|
||||
<span className="countdown__label">H :</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--2 js-countdown__value--2">
|
||||
{timeLeft.minutes}
|
||||
</span>
|
||||
<span className="countdown__label">M :</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--3 js-countdown__value--3">
|
||||
{timeLeft.seconds}
|
||||
</span>
|
||||
<span className="countdown__label">S</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{style == 2 && (
|
||||
<div aria-hidden="true" className="countdown__timer">
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--0 js-countdown__value--0">
|
||||
{timeLeft.days}
|
||||
</span>
|
||||
<span className="countdown__label">Days</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--1 js-countdown__value--1">
|
||||
{timeLeft.hours}
|
||||
</span>
|
||||
<span className="countdown__label">Hours</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--2 js-countdown__value--2">
|
||||
{timeLeft.minutes}
|
||||
</span>
|
||||
<span className="countdown__label">Mins</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--3 js-countdown__value--3">
|
||||
{timeLeft.seconds}
|
||||
</span>
|
||||
<span className="countdown__label">Secs</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{style == 3 && (
|
||||
<div aria-hidden="true" className="countdown__timer">
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--0 js-countdown__value--0">
|
||||
{timeLeft.days}
|
||||
</span>
|
||||
<span className="countdown__label">DAYS</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--1 js-countdown__value--1">
|
||||
{timeLeft.hours}
|
||||
</span>
|
||||
<span className="countdown__label">HOURS</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--2 js-countdown__value--2">
|
||||
{timeLeft.minutes}
|
||||
</span>
|
||||
<span className="countdown__label">MINUTES</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--3 js-countdown__value--3">
|
||||
{timeLeft.seconds}
|
||||
</span>
|
||||
<span className="countdown__label">SECONDS</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{style == 4 && (
|
||||
<div aria-hidden="true" class="countdown__timer">
|
||||
<span class="countdown__item">
|
||||
<span class="countdown__value countdown__value--2 js-countdown__value--2">
|
||||
{timeLeft.minutes}
|
||||
</span>
|
||||
<span class="countdown__label">:</span>
|
||||
</span>
|
||||
<span class="countdown__item">
|
||||
<span class="countdown__value countdown__value--3 js-countdown__value--3">
|
||||
{timeLeft.seconds}
|
||||
</span>
|
||||
<span class="countdown__label"></span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{style == 5 && (
|
||||
<div aria-hidden="true" className="countdown__timer">
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--0 js-countdown__value--0">
|
||||
{timeLeft.days}
|
||||
</span>
|
||||
<span className="countdown__label">d :</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--1 js-countdown__value--1">
|
||||
{timeLeft.hours}
|
||||
</span>
|
||||
<span className="countdown__label">h :</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--2 js-countdown__value--2">
|
||||
{timeLeft.minutes}
|
||||
</span>
|
||||
<span className="countdown__label">m :</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--3 js-countdown__value--3">
|
||||
{timeLeft.seconds}
|
||||
</span>
|
||||
<span className="countdown__label">s</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
{style == 6 && (
|
||||
<div aria-hidden="true" className="countdown__timer">
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--0 js-countdown__value--0">
|
||||
{timeLeft.days}
|
||||
</span>
|
||||
<span className="countdown__label">D</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--1 js-countdown__value--1">
|
||||
{timeLeft.hours}
|
||||
</span>
|
||||
<span className="countdown__label">H</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--2 js-countdown__value--2">
|
||||
{timeLeft.minutes}
|
||||
</span>
|
||||
<span className="countdown__label">M</span>
|
||||
</span>
|
||||
<span className="countdown__item">
|
||||
<span className="countdown__value countdown__value--3 js-countdown__value--3">
|
||||
{timeLeft.seconds}
|
||||
</span>
|
||||
<span className="countdown__label">S</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CountdownTimer;
|
||||
91
components/common/DropdownSelect.jsx
Normal file
91
components/common/DropdownSelect.jsx
Normal file
@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
const optionsDefault = ["Newest", "Oldest", "3 days"];
|
||||
export default function DropdownSelect({
|
||||
onChange = (elm) => {},
|
||||
options = optionsDefault,
|
||||
defaultOption,
|
||||
selectedValue,
|
||||
addtionalParentClass = "",
|
||||
}) {
|
||||
const selectRef = useRef();
|
||||
const optionsRef = useRef();
|
||||
const [selected, setSelected] = useState("");
|
||||
const toggleDropdown = () => {
|
||||
selectRef.current.classList.toggle("open");
|
||||
};
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (!selectRef.current.contains(event.target)) {
|
||||
selectRef.current.classList.remove("open");
|
||||
}
|
||||
};
|
||||
|
||||
// Add event listeners to each dropdown element
|
||||
|
||||
// Add a global click event listener to detect outside clicks
|
||||
document.addEventListener("click", handleClickOutside);
|
||||
|
||||
// Cleanup event listeners on component unmount
|
||||
return () => {
|
||||
document.removeEventListener("click", handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Function to handle clicks outside the select or options
|
||||
const handleClickOutside = (event) => {
|
||||
if (
|
||||
selectRef.current &&
|
||||
selectRef.current.contains(event.target) &&
|
||||
optionsRef.current &&
|
||||
!optionsRef.current.contains(event.target)
|
||||
) {
|
||||
// Close the options if clicked outside
|
||||
toggleDropdown();
|
||||
}
|
||||
};
|
||||
|
||||
// Add event listener on mount
|
||||
document.addEventListener("click", handleClickOutside);
|
||||
|
||||
// Cleanup event listener on unmount
|
||||
return () => {
|
||||
document.removeEventListener("click", handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={`nice-select ${addtionalParentClass}`} ref={selectRef}>
|
||||
<span className="current">
|
||||
{selectedValue || selected || defaultOption || options[0]}
|
||||
</span>
|
||||
<ul className="list" ref={optionsRef}>
|
||||
{options.map((elm, i) => (
|
||||
<li
|
||||
key={i}
|
||||
onClick={() => {
|
||||
setSelected(elm);
|
||||
onChange(elm);
|
||||
toggleDropdown();
|
||||
}}
|
||||
className={`option ${
|
||||
!selectedValue
|
||||
? selected == elm
|
||||
? "selected"
|
||||
: ""
|
||||
: selectedValue == elm
|
||||
? "selected"
|
||||
: ""
|
||||
} text text-1`}
|
||||
>
|
||||
{elm}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
212
components/common/Faqs.jsx
Normal file
212
components/common/Faqs.jsx
Normal file
@ -0,0 +1,212 @@
|
||||
import React from "react";
|
||||
|
||||
export default function Faqs({
|
||||
parentClass = "section-faqs style-1 tf-spacing-8 pt-0",
|
||||
headingClass = "heading-title split-text effect-right",
|
||||
header2 = false,
|
||||
}) {
|
||||
return (
|
||||
<div className={parentClass}>
|
||||
<div className="tf-container">
|
||||
<div
|
||||
className={`heading-section text-center ${
|
||||
header2 ? "mb_86" : "mb_92"
|
||||
} `}
|
||||
>
|
||||
{header2 ? (
|
||||
<h2 className={headingClass}>Got a question? Get your answer</h2>
|
||||
) : (
|
||||
<h1 className={headingClass}>Got a question? Get your answer</h1>
|
||||
)}
|
||||
<p
|
||||
className="text-body-1 text_mono-gray-7 mt_20 wow animate__fadeInUp animate__animated"
|
||||
data-wow-delay="0s"
|
||||
>
|
||||
We revolutionize industries with dynamic digital solutions, tailored
|
||||
to meet contemporary demands and <br />
|
||||
drive impactful transformations for businesses of all sectors.
|
||||
</p>
|
||||
</div>
|
||||
<ul
|
||||
className="accordion-wrap gap-16 style-faqs d-grid gap_16"
|
||||
id="accordion-faq-1"
|
||||
>
|
||||
<li className="accordion-item action_click scrolling-effect effectBottom style-default v2">
|
||||
<a
|
||||
href="#accordion-1"
|
||||
className="accordion-title action collapsed current"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="true"
|
||||
aria-controls="accordion-1"
|
||||
>
|
||||
<div className="heading">
|
||||
<h5 className="title">
|
||||
How benefit that We got when choose Basic plan?
|
||||
</h5>
|
||||
</div>
|
||||
<span className="icon" />
|
||||
</a>
|
||||
<div
|
||||
id="accordion-1"
|
||||
className="collapse"
|
||||
data-bs-parent="#accordion-faq-1"
|
||||
>
|
||||
<div className="accordion-faqs-content">
|
||||
<p className="text-body-2 lh-20">
|
||||
Through the collaboration with customers in discussing needs
|
||||
and demand, we’re able to attain <br />
|
||||
mutual understand again customer trust to offer appropriate
|
||||
advice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="accordion-item action_click scrolling-effect effectBottom active style-default v2">
|
||||
<a
|
||||
href="#accordion-2"
|
||||
className="accordion-title action current"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="true"
|
||||
aria-controls="accordion-2"
|
||||
>
|
||||
<div className="heading">
|
||||
<h5 className="title">Our project will 100% Secure?</h5>
|
||||
</div>
|
||||
<span className="icon" />
|
||||
</a>
|
||||
<div
|
||||
id="accordion-2"
|
||||
className="collapse show"
|
||||
data-bs-parent="#accordion-faq-1"
|
||||
>
|
||||
<div className="accordion-faqs-content">
|
||||
<p className="text-body-2 lh-20">
|
||||
Through the collaboration with customers in discussing needs
|
||||
and demand, we’re able to attain <br />
|
||||
mutual understand again customer trust to offer appropriate
|
||||
advice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="accordion-item action_click scrolling-effect effectBottom style-default v2">
|
||||
<a
|
||||
href="#accordion-3"
|
||||
className="accordion-title action collapsed current"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="true"
|
||||
aria-controls="accordion-3"
|
||||
>
|
||||
<div className="heading">
|
||||
<h5 className="title">NDA Agreement will include?</h5>
|
||||
</div>
|
||||
<span className="icon" />
|
||||
</a>
|
||||
<div
|
||||
id="accordion-3"
|
||||
className="collapse"
|
||||
data-bs-parent="#accordion-faq-1"
|
||||
>
|
||||
<div className="accordion-faqs-content">
|
||||
<p className="text-body-2 lh-20">
|
||||
Through the collaboration with customers in discussing needs
|
||||
and demand, we’re able to attain <br />
|
||||
mutual understand again customer trust to offer appropriate
|
||||
advice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="accordion-item action_click scrolling-effect effectBottom style-default v2">
|
||||
<a
|
||||
href="#accordion-4"
|
||||
className="accordion-title action collapsed current"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="true"
|
||||
aria-controls="accordion-4"
|
||||
>
|
||||
<div className="heading">
|
||||
<h5 className="title">
|
||||
Can my premium license be used for all devices?
|
||||
</h5>
|
||||
</div>
|
||||
<span className="icon" />
|
||||
</a>
|
||||
<div
|
||||
id="accordion-4"
|
||||
className="collapse"
|
||||
data-bs-parent="#accordion-faq-1"
|
||||
>
|
||||
<div className="accordion-faqs-content">
|
||||
<p className="text-body-2 lh-20">
|
||||
Through the collaboration with customers in discussing needs
|
||||
and demand, we’re able to attain <br />
|
||||
mutual understand again customer trust to offer appropriate
|
||||
advice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="accordion-item action_click scrolling-effect effectBottom style-default v2">
|
||||
<a
|
||||
href="#accordion-5"
|
||||
className="accordion-title action collapsed current"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="true"
|
||||
aria-controls="accordion-5"
|
||||
>
|
||||
<div className="heading">
|
||||
<h5 className="title">
|
||||
What things that we need provide when choose your service
|
||||
</h5>
|
||||
</div>
|
||||
<span className="icon" />
|
||||
</a>
|
||||
<div
|
||||
id="accordion-5"
|
||||
className="collapse"
|
||||
data-bs-parent="#accordion-faq-1"
|
||||
>
|
||||
<div className="accordion-faqs-content">
|
||||
<p className="text-body-2 lh-20">
|
||||
Through the collaboration with customers in discussing needs
|
||||
and demand, we’re able to attain <br />
|
||||
mutual understand again customer trust to offer appropriate
|
||||
advice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="accordion-item action_click scrolling-effect effectBottom style-default v2">
|
||||
<a
|
||||
href="#accordion-6"
|
||||
className="accordion-title action collapsed current"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="true"
|
||||
aria-controls="accordion-6"
|
||||
>
|
||||
<div className="heading">
|
||||
<h5 className="title">How long for a standard project?</h5>
|
||||
</div>
|
||||
<span className="icon" />
|
||||
</a>
|
||||
<div
|
||||
id="accordion-6"
|
||||
className="collapse"
|
||||
data-bs-parent="#accordion-faq-1"
|
||||
>
|
||||
<div className="accordion-faqs-content">
|
||||
<p className="text-body-2 lh-20">
|
||||
Through the collaboration with customers in discussing needs
|
||||
and demand, we’re able to attain <br />
|
||||
mutual understand again customer trust to offer appropriate
|
||||
advice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
311
components/common/LayoutWrapper.jsx
Normal file
311
components/common/LayoutWrapper.jsx
Normal file
@ -0,0 +1,311 @@
|
||||
"use client";
|
||||
|
||||
import { usePathname } from "next/navigation";
|
||||
import React, { useEffect } from "react";
|
||||
import SplitText from "@/utlis/splitText";
|
||||
import gsap from "gsap";
|
||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
export default function LayoutWrapper({ children }) {
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
// Import the script only on the client side
|
||||
import("bootstrap/dist/js/bootstrap.esm").then(() => {
|
||||
// Module is imported, you can access any exported functionality if
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
let lastScrollTop = 0;
|
||||
const delta = 10;
|
||||
const header = document.querySelector(".header");
|
||||
|
||||
const handleScroll = () => {
|
||||
const scrollTop = window.scrollY;
|
||||
|
||||
if (scrollTop < 350) {
|
||||
header?.classList.remove("is-sticky");
|
||||
if (scrollTop < 200) {
|
||||
header?.classList.remove("header-sticky");
|
||||
} else {
|
||||
header?.classList.add("header-sticky");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (scrollTop > lastScrollTop + delta) {
|
||||
header?.classList.add("header-sticky");
|
||||
header?.classList.remove("is-sticky");
|
||||
} else if (scrollTop < lastScrollTop - delta) {
|
||||
header?.classList.add("is-sticky");
|
||||
}
|
||||
lastScrollTop = scrollTop;
|
||||
};
|
||||
setTimeout(() => {
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
window.dispatchEvent(new Event("scroll"));
|
||||
});
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
};
|
||||
}, [pathname]);
|
||||
useEffect(() => {
|
||||
// Scrolling Effect
|
||||
const scrollingEffect = () => {
|
||||
const elements = document.querySelectorAll(".scrolling-effect");
|
||||
if (!elements.length) return;
|
||||
|
||||
elements.forEach((el) => {
|
||||
const settings = {
|
||||
scrollTrigger: {
|
||||
trigger: el,
|
||||
scrub: 3,
|
||||
toggleActions: "play none none reverse",
|
||||
start: "top bottom",
|
||||
end: "bottom bottom",
|
||||
delay: 3,
|
||||
},
|
||||
duration: 0.8,
|
||||
ease: "power3.out",
|
||||
};
|
||||
|
||||
if (el.classList.contains("effectRight")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "80";
|
||||
}
|
||||
if (el.classList.contains("effectLeft")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "-80";
|
||||
}
|
||||
if (el.classList.contains("effectBottom")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "100";
|
||||
}
|
||||
if (el.classList.contains("effectTop")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "-80";
|
||||
}
|
||||
if (el.classList.contains("effectZoomIn")) {
|
||||
settings.opacity = 0;
|
||||
settings.scale = 0.5;
|
||||
}
|
||||
|
||||
gsap.from(el, settings);
|
||||
});
|
||||
};
|
||||
|
||||
// Animation Text
|
||||
const animationText = () => {
|
||||
const splitTextElements = document.querySelectorAll(".split-text");
|
||||
if (!splitTextElements.length) return;
|
||||
|
||||
splitTextElements.forEach((el) => {
|
||||
const target = el.querySelector("p, a") || el;
|
||||
const pxlSplit = new SplitText(target, {
|
||||
type: "words, chars, lines",
|
||||
lineThreshold: 0.5,
|
||||
wordsClass: "word",
|
||||
linesClass: "split-line",
|
||||
});
|
||||
|
||||
// Handle gradient characters
|
||||
const gradientChars = el.querySelectorAll(".text-gradient > .word > *");
|
||||
if (gradientChars.length) {
|
||||
let offset = 0;
|
||||
gradientChars.forEach((char) => {
|
||||
const parent = char.parentElement;
|
||||
const parentWidth = parent.offsetWidth;
|
||||
|
||||
char.style.backgroundSize = `${parentWidth}px 100%`;
|
||||
offset += char.previousElementSibling?.offsetWidth || 0;
|
||||
char.style.backgroundPosition = `${parentWidth - offset}px 0%`;
|
||||
});
|
||||
}
|
||||
|
||||
let splitTypeSet = pxlSplit.chars;
|
||||
gsap.set(target, { perspective: 400 });
|
||||
|
||||
const settings = {
|
||||
scrollTrigger: {
|
||||
trigger: target,
|
||||
start: "top 86%",
|
||||
once: true,
|
||||
},
|
||||
duration: 0.9,
|
||||
stagger: 0.02,
|
||||
ease: "power3.out",
|
||||
};
|
||||
|
||||
const hasClass = (className) => el.classList.contains(className);
|
||||
|
||||
if (hasClass("effect-fade")) settings.opacity = 0;
|
||||
if (hasClass("effect-right")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "50";
|
||||
}
|
||||
if (hasClass("effect-left")) {
|
||||
settings.opacity = 0;
|
||||
settings.x = "-50";
|
||||
}
|
||||
if (hasClass("effect-up")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "80";
|
||||
}
|
||||
if (hasClass("effect-down")) {
|
||||
settings.opacity = 0;
|
||||
settings.y = "-80";
|
||||
}
|
||||
if (hasClass("effect-rotate")) {
|
||||
settings.opacity = 0;
|
||||
settings.rotateX = "50deg";
|
||||
}
|
||||
if (hasClass("effect-scale")) {
|
||||
settings.opacity = 0;
|
||||
settings.scale = "0.5";
|
||||
}
|
||||
|
||||
if (
|
||||
hasClass("split-lines-transform") ||
|
||||
hasClass("split-lines-rotation-x")
|
||||
) {
|
||||
pxlSplit.split({
|
||||
type: "lines",
|
||||
lineThreshold: 0.5,
|
||||
linesClass: "split-line",
|
||||
});
|
||||
|
||||
splitTypeSet = pxlSplit.lines;
|
||||
settings.opacity = 0;
|
||||
settings.stagger = 0.5;
|
||||
|
||||
if (hasClass("split-lines-rotation-x")) {
|
||||
settings.rotationX = -120;
|
||||
settings.transformOrigin = "top center -50";
|
||||
} else {
|
||||
settings.yPercent = 100;
|
||||
settings.autoAlpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasClass("split-words-scale")) {
|
||||
pxlSplit.split({ type: "words" });
|
||||
splitTypeSet = pxlSplit.words;
|
||||
|
||||
splitTypeSet.forEach((elw, index) => {
|
||||
gsap.set(
|
||||
elw,
|
||||
{
|
||||
opacity: 0,
|
||||
scale: index % 2 === 0 ? 0 : 2,
|
||||
force3D: true,
|
||||
duration: 0.1,
|
||||
ease: "power3.out",
|
||||
stagger: 0.02,
|
||||
},
|
||||
index * 0.01
|
||||
);
|
||||
});
|
||||
|
||||
gsap.to(splitTypeSet, {
|
||||
scrollTrigger: {
|
||||
trigger: el,
|
||||
start: "top 86%",
|
||||
},
|
||||
rotateX: "0",
|
||||
scale: 1,
|
||||
opacity: 1,
|
||||
});
|
||||
} else {
|
||||
gsap.from(splitTypeSet, settings);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Initialize effects
|
||||
setTimeout(() => {
|
||||
scrollingEffect();
|
||||
animationText();
|
||||
});
|
||||
}, [pathname]);
|
||||
useEffect(() => {
|
||||
const WOW = require("@/utlis/wow");
|
||||
const wow = new WOW.default({
|
||||
mobile: false,
|
||||
live: false,
|
||||
});
|
||||
wow.init();
|
||||
}, [pathname]);
|
||||
useEffect(() => {
|
||||
// Dynamically import Bootstrap
|
||||
import("bootstrap")
|
||||
.then((bootstrap) => {
|
||||
// Close any open modal
|
||||
const modalElements = document.querySelectorAll(".modal.show");
|
||||
modalElements.forEach((modal) => {
|
||||
const modalInstance = bootstrap.Modal.getInstance(modal);
|
||||
if (modalInstance) {
|
||||
modalInstance.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Close any open offcanvas
|
||||
const offcanvasElements = document.querySelectorAll(".offcanvas.show");
|
||||
offcanvasElements.forEach((offcanvas) => {
|
||||
const offcanvasInstance = bootstrap.Offcanvas.getInstance(offcanvas);
|
||||
if (offcanvasInstance) {
|
||||
offcanvasInstance.hide();
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error loading Bootstrap:", error);
|
||||
});
|
||||
}, [pathname]); // Runs every time the route changes
|
||||
useEffect(() => {
|
||||
const scrollTransformElements =
|
||||
document.querySelectorAll(".scroll-tranform");
|
||||
|
||||
if (scrollTransformElements.length > 0) {
|
||||
scrollTransformElements.forEach((element) => {
|
||||
const direction = element.dataset.direction || "up";
|
||||
const distance = element.dataset.distance || "10%";
|
||||
let animationProperty;
|
||||
|
||||
switch (direction.toLowerCase()) {
|
||||
case "left":
|
||||
animationProperty = { x: `-${distance}` };
|
||||
break;
|
||||
case "right":
|
||||
animationProperty = { x: `${distance}` };
|
||||
break;
|
||||
case "up":
|
||||
animationProperty = { y: `-${distance}` };
|
||||
break;
|
||||
case "down":
|
||||
animationProperty = { y: `${distance}` };
|
||||
break;
|
||||
default:
|
||||
animationProperty = { y: `-${distance}` };
|
||||
}
|
||||
|
||||
gsap.to(element, {
|
||||
...animationProperty,
|
||||
scrollTrigger: {
|
||||
trigger: element,
|
||||
start: "top center",
|
||||
end: "bottom top",
|
||||
scrub: 2,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Optional cleanup
|
||||
return () => {
|
||||
ScrollTrigger.getAll().forEach((trigger) => trigger.kill());
|
||||
};
|
||||
}, [pathname]);
|
||||
return <>{children}</>;
|
||||
}
|
||||
70
components/common/OdometerComponent.jsx
Normal file
70
components/common/OdometerComponent.jsx
Normal file
@ -0,0 +1,70 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
|
||||
const OdometerComponent = ({ max }) => {
|
||||
const odometerRef = useRef(null);
|
||||
const [value, setValue] = useState(0);
|
||||
const odometerInitRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
import("odometer").then((Odometer) => {
|
||||
// Initialize Odometer or do something with it
|
||||
|
||||
// Example usage of Odometer
|
||||
if (Odometer && odometerRef.current) {
|
||||
odometerInitRef.current = new Odometer.default({
|
||||
el: odometerRef.current,
|
||||
value,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (odometerRef.current && odometerInitRef.current) {
|
||||
odometerInitRef.current.update(value); // Update odometer when value changes
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
const startCountup = () => {
|
||||
setValue(max);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleIntersection = (entries, observer) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
startCountup();
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const options = {
|
||||
root: null,
|
||||
rootMargin: "0px",
|
||||
threshold: 0.5,
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver(handleIntersection, options);
|
||||
if (odometerRef.current) {
|
||||
observer.observe(odometerRef.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (odometerRef.current) {
|
||||
observer.unobserve(odometerRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div ref={odometerRef} className="odometer">
|
||||
0
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default OdometerComponent;
|
||||
59
components/common/Pricing.jsx
Normal file
59
components/common/Pricing.jsx
Normal file
@ -0,0 +1,59 @@
|
||||
import { pricingPlans } from "@/data/pricing";
|
||||
import React from "react";
|
||||
|
||||
export default function Pricing({
|
||||
parentClass = "section-pricing style-1 tf-spacing-6",
|
||||
}) {
|
||||
return (
|
||||
<div className={parentClass}>
|
||||
<div className="tf-container">
|
||||
<div className="wrap">
|
||||
<div className="heading-section mb_88">
|
||||
<h2>Choose A Plan, Start Now.</h2>
|
||||
<p className="text-body-1 text_mono-gray-7 mt_20">
|
||||
Whether you’re just getting started with rapid testing or scaling
|
||||
across the <br />
|
||||
organization, we’ve got you covered
|
||||
</p>
|
||||
</div>
|
||||
<div className="tf-grid-layout lg-col-3">
|
||||
{pricingPlans.map((plan, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`pricing-item${plan.isHighlighted ? " center" : ""}`}
|
||||
>
|
||||
<div className="content">
|
||||
<div className="heading">
|
||||
<h5 className="title mb_4">{plan.title}</h5>
|
||||
<p className="text-body-2 text_mono-gray-7">
|
||||
{plan.description}
|
||||
</p>
|
||||
</div>
|
||||
<div className="price d-flex align-items-end">
|
||||
<h3 className="text_primary price-value">{plan.price}</h3>
|
||||
<span className="text_mono-gray-7 sub-heading">/month</span>
|
||||
</div>
|
||||
<ul className="list d-grid gap_16">
|
||||
{plan.features.map((feature, i) => (
|
||||
<li
|
||||
key={i}
|
||||
className="sub-heading d-flex gap_16 align-items-center"
|
||||
>
|
||||
<i className="icon-check-solid text_primary" />
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<a href="#" className={plan.buttonStyle}>
|
||||
<span className="text-body-3">Get Started Now</span>
|
||||
<span className="bg-effect" />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
90
components/common/ScrollTop.jsx
Normal file
90
components/common/ScrollTop.jsx
Normal file
@ -0,0 +1,90 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function ScrollTop() {
|
||||
useEffect(() => {
|
||||
const box = document.querySelector(".scrollTop");
|
||||
const liquid = document.querySelector(".liquid");
|
||||
const offset = 200;
|
||||
|
||||
const handleScroll = () => {
|
||||
const scrollPosition = window.scrollY;
|
||||
const docHeight =
|
||||
document.documentElement.scrollHeight - window.innerHeight;
|
||||
const percent = Math.min(
|
||||
Math.floor((scrollPosition / docHeight) * 100),
|
||||
100
|
||||
);
|
||||
|
||||
if (liquid) {
|
||||
liquid.style.transform = `translate(0, ${100 - percent}%)`;
|
||||
}
|
||||
|
||||
if (scrollPosition >= offset) {
|
||||
box?.classList.add("active-progress");
|
||||
} else {
|
||||
box?.classList.remove("active-progress");
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = (event) => {
|
||||
event.preventDefault();
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
};
|
||||
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
box?.addEventListener("click", handleClick);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
box?.removeEventListener("click", handleClick);
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<div className="scrollTop effect-icon">
|
||||
<div className="icon">
|
||||
<i className="icon-long-arrow-alt-up-solid" />
|
||||
</div>
|
||||
<div className="liquid">
|
||||
<svg viewBox="0 0 560 20" className="liquid_wave liquid_wave_back">
|
||||
<use xlinkHref="#wave" />
|
||||
</svg>
|
||||
<svg viewBox="0 0 560 20" className="liquid_wave liquid_wave_front">
|
||||
<use xlinkHref="#liquid" />
|
||||
</svg>
|
||||
<svg
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 560 20"
|
||||
style={{ display: "none" }}
|
||||
>
|
||||
<symbol id="liquid">
|
||||
<path
|
||||
d="M420,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C514,6.5,518,4.7,528.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H420z"
|
||||
fill="#"
|
||||
style={{
|
||||
transition: "stroke-dashoffset 10ms linear",
|
||||
strokeDasharray: "301.839, 301.839",
|
||||
strokeDashoffset: "251.895px",
|
||||
}}
|
||||
/>
|
||||
<path
|
||||
d="M420,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C326,6.5,322,4.7,311.5,2.7C304.3,1.4,293.6-0.1,280,0c0,0,0,0,0,0v20H420z"
|
||||
fill="#"
|
||||
/>
|
||||
<path
|
||||
d="M140,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C234,6.5,238,4.7,248.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H140z"
|
||||
fill="#"
|
||||
/>
|
||||
<path
|
||||
d="M140,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C46,6.5,42,4.7,31.5,2.7C24.3,1.4,13.6-0.1,0,0c0,0,0,0,0,0l0,20H140z"
|
||||
fill="#"
|
||||
/>
|
||||
</symbol>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
153
components/common/Services.jsx
Normal file
153
components/common/Services.jsx
Normal file
@ -0,0 +1,153 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { Pagination } from "swiper/modules";
|
||||
const services = [
|
||||
{
|
||||
title: (
|
||||
<>
|
||||
Business Strategy <br /> Planning
|
||||
</>
|
||||
),
|
||||
imgSrc: "/images/box-icon/business-idea.png",
|
||||
description:
|
||||
"Market analysis and research, Competitive landscape assessment, SWOT analysis, Strategic goal setting.",
|
||||
delay: "0s",
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<>
|
||||
Financial Consulting
|
||||
<br />
|
||||
& Strategy
|
||||
</>
|
||||
),
|
||||
imgSrc: "/images/box-icon/currency-exchange.png",
|
||||
description:
|
||||
"Financial statement analysis, Cost-benefit analysis, Budgeting and forecasting, Risk management.",
|
||||
delay: ".15s",
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<>
|
||||
Operations & Analyst
|
||||
<br />
|
||||
Improvement
|
||||
</>
|
||||
),
|
||||
imgSrc: "/images/box-icon/stock-market.png",
|
||||
description:
|
||||
"Process Optimization, Lean Manufacturing, Supply Chain Management, Quality Control.",
|
||||
delay: ".25s",
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<>
|
||||
Tailor Personnel <br /> Consulting
|
||||
</>
|
||||
),
|
||||
imgSrc: "/images/box-icon/email-marketing.png",
|
||||
description:
|
||||
"Talent Acquisition, Employee Development, Performance Management, Organizational Culture Development.",
|
||||
delay: ".35s",
|
||||
},
|
||||
];
|
||||
|
||||
export default function Services() {
|
||||
return (
|
||||
<div className="section section-service style-1 bg-sub-color tf-spacing-16">
|
||||
<div className="tf-container">
|
||||
<div className="heading-section d-flex justify-content-between flex-wrap-md gap_12 align-items-end mb_112">
|
||||
<div className="left">
|
||||
<h2 className="heading-title split-text effect-right">
|
||||
Tailored Solutions For Your Growth
|
||||
</h2>
|
||||
<p
|
||||
className="text-body-1 text_mono-gray-7 mt_20 wow animate__fadeInUp animate__animated"
|
||||
data-wow-delay="0s"
|
||||
>
|
||||
With custom services, we empower the development, provide support
|
||||
from your unique vision.
|
||||
</p>
|
||||
</div>
|
||||
<Link href={`/services`} className="tf-btn btn-primary2">
|
||||
<span>View Services</span>
|
||||
<span className="bg-effect" />
|
||||
</Link>
|
||||
</div>
|
||||
<Swiper
|
||||
className="swiper tf-sw-mobile bg_1 swiper-active-576"
|
||||
data-screen={576}
|
||||
spaceBetween={15}
|
||||
modules={[Pagination]}
|
||||
pagination={{
|
||||
clickable: true,
|
||||
el: ".spd16",
|
||||
}}
|
||||
>
|
||||
{services.map((service, index) => (
|
||||
<SwiperSlide
|
||||
key={index}
|
||||
className="swiper-slide wow animate__fadeInRight animate__animated"
|
||||
data-wow-delay={service.delay}
|
||||
>
|
||||
<div className="tf-box-icon style-1 hover-border">
|
||||
<h5 className="mb_53 title">
|
||||
<a href="#" className="link hover-line-text line-clamp-2">
|
||||
{service.title}
|
||||
</a>
|
||||
</h5>
|
||||
<div className="icon">
|
||||
<Image
|
||||
alt="icon"
|
||||
src={service.imgSrc}
|
||||
width={160}
|
||||
height={160}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-body-1 text_mono-gray-7">
|
||||
{service.description}
|
||||
</p>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
|
||||
<div className="sw-dots style-default spd16 sw-pagination-mb mt_20 justify-content-center d-flex d-md-none" />
|
||||
</Swiper>
|
||||
<div className="swiper tf-sw-mobile bg_1 swiper-inActive-576">
|
||||
<div className="swiper-wrapper tf-grid-layout-sm xl-col-4 sm-col-2 gap_24">
|
||||
{services.map((service, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="swiper-slide wow animate__fadeInRight animate__animated"
|
||||
data-wow-delay={service.delay}
|
||||
>
|
||||
<div className="tf-box-icon style-1 hover-border">
|
||||
<h5 className="mb_53 title">
|
||||
<a href="#" className="link hover-line-text line-clamp-2">
|
||||
{service.title}
|
||||
</a>
|
||||
</h5>
|
||||
<div className="icon">
|
||||
<Image
|
||||
alt="icon"
|
||||
src={service.imgSrc}
|
||||
width={160}
|
||||
height={160}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-body-1 text_mono-gray-7">
|
||||
{service.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="sw-dots style-default sw-pagination-mb mt_20 justify-content-center d-flex d-md-none" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
136
components/common/Testimonials.jsx
Normal file
136
components/common/Testimonials.jsx
Normal file
@ -0,0 +1,136 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { testimonials3 } from "@/data/testimonials";
|
||||
export default function Testimonials() {
|
||||
return (
|
||||
<div className="section-testimonial style-1">
|
||||
<div className="tf-container">
|
||||
<div className="row">
|
||||
<div className="col-lg-6">
|
||||
<div className="wrap">
|
||||
<div className="heading-section">
|
||||
<h2 className="heading-title split-text split-lines-rotation-x">
|
||||
Client Satisfaction, Our Reputation
|
||||
</h2>
|
||||
<p
|
||||
className="text-body-1 text_mono-gray-7 mt_20 wow animate__fadeInUp animate__animated"
|
||||
data-wow-delay="0s"
|
||||
>
|
||||
We’ve helped hundreds of partners, to achieve their goals and
|
||||
stellar feedback, is our reward!
|
||||
</p>
|
||||
</div>
|
||||
<div className="item">
|
||||
<Image
|
||||
alt="item"
|
||||
src="/images/item/item-testimonial1.png"
|
||||
width={715}
|
||||
height={330}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6">
|
||||
<div className="tf-grid-layout md-col-2">
|
||||
<div
|
||||
className="infiniteslide_wrap"
|
||||
style={{ overflow: "hidden", height: 2370 }}
|
||||
>
|
||||
<div className="infiniteslide infiniteSlideVertical">
|
||||
{[...testimonials3, ...testimonials3].map(
|
||||
(testimonial, index) => (
|
||||
<div
|
||||
key={`${testimonial.id}-${index}`}
|
||||
className={`testimonial style-default ${
|
||||
index >= 6 ? "infiniteslide_clone" : ""
|
||||
}`}
|
||||
style={{ flex: "0 0 auto", display: "block" }}
|
||||
>
|
||||
<div className="icon mb_30">
|
||||
<i className="icon-quote" />
|
||||
</div>
|
||||
<div className="text sub-heading mb_30">
|
||||
“ {testimonial.quote} ”
|
||||
</div>
|
||||
<div className="box-user d-flex align-items-center">
|
||||
<div className="avatar">
|
||||
<Image
|
||||
alt="avatar"
|
||||
src={testimonial.avatar}
|
||||
width={100}
|
||||
height={100}
|
||||
/>
|
||||
</div>
|
||||
<div className="content">
|
||||
<p className="text-body-3 sub font3 text_mono-gray-6">
|
||||
{testimonial.position}
|
||||
</p>
|
||||
<div className="text-body-2 text_black name text-uppercase">
|
||||
<a href="#" className="link">
|
||||
{testimonial.name}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="infiniteslide_wrap"
|
||||
style={{ overflow: "hidden", height: 2370 }}
|
||||
>
|
||||
<div
|
||||
className="infiniteslide infiniteSlideVertical"
|
||||
style={{ animationDirection: "reverse" }}
|
||||
>
|
||||
{[...testimonials3, ...testimonials3].map(
|
||||
(testimonial, index) => (
|
||||
<div
|
||||
key={`${testimonial.id}-${index}`}
|
||||
className={`testimonial style-default ${
|
||||
index >= 6 ? "infiniteslide_clone" : ""
|
||||
}`}
|
||||
style={{ flex: "0 0 auto", display: "block" }}
|
||||
>
|
||||
<div className="icon mb_30">
|
||||
<i className="icon-quote" />
|
||||
</div>
|
||||
<div className="text sub-heading mb_30">
|
||||
“ {testimonial.quote} ”
|
||||
</div>
|
||||
<div className="box-user d-flex align-items-center">
|
||||
<div className="avatar">
|
||||
<Image
|
||||
alt="avatar"
|
||||
src={testimonial.avatar}
|
||||
width={100}
|
||||
height={100}
|
||||
/>
|
||||
</div>
|
||||
<div className="content">
|
||||
<p className="text-body-3 sub font3 text_mono-gray-6">
|
||||
{testimonial.position}
|
||||
</p>
|
||||
<div className="text-body-2 text_black name text-uppercase">
|
||||
<a href="#" className="link">
|
||||
{testimonial.name}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user