first commit
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
import Link from "next/link"
|
||||
export default function BackToTop() {
|
||||
const [hasScrolled, setHasScrolled] = useState("false")
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("scroll", onScroll)
|
||||
return () => {
|
||||
window.removeEventListener("scroll", onScroll)
|
||||
}
|
||||
})
|
||||
|
||||
const onScroll = () => {
|
||||
if (window.scrollY > 100 && !hasScrolled) {
|
||||
setHasScrolled(true)
|
||||
} else if (window.scrollY < 100 && hasScrolled) {
|
||||
setHasScrolled(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasScrolled && (
|
||||
<Link className="scroll__top scroll-to-target open" href="#top" style={{ position: 'fixed', zIndex: 2147483647 }}>
|
||||
<i className="fas fa-angle-up"></i>
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
|
||||
export default function Counter({ end, duration }) {
|
||||
const [count, setCount] = useState(0)
|
||||
const countRef = useRef(null)
|
||||
const increment = end / duration
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry.isIntersecting) {
|
||||
startCount()
|
||||
observer.disconnect()
|
||||
}
|
||||
},
|
||||
{ threshold: 0 }
|
||||
)
|
||||
|
||||
if (countRef.current) {
|
||||
observer.observe(countRef.current)
|
||||
}
|
||||
|
||||
return () => {
|
||||
observer.disconnect()
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setCount((prevCount) => {
|
||||
const newCount = prevCount + increment
|
||||
if (newCount >= end) {
|
||||
clearInterval(interval)
|
||||
return end
|
||||
} else {
|
||||
return newCount
|
||||
}
|
||||
})
|
||||
}, 1000 / duration)
|
||||
|
||||
return () => {
|
||||
clearInterval(interval)
|
||||
}
|
||||
}, [end, increment])
|
||||
|
||||
const startCount = () => {
|
||||
setCount(0)
|
||||
}
|
||||
|
||||
return (
|
||||
<span ref={countRef}>
|
||||
<span>{Math.round(count)}</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import Counter from './Counter'
|
||||
|
||||
export default function CounterUp({ end }) {
|
||||
const [inViewport, setInViewport] = useState(false)
|
||||
|
||||
const handleScroll = () => {
|
||||
const elements = document.getElementsByClassName('count-element')
|
||||
if (elements.length > 0) {
|
||||
const element = elements[0]
|
||||
const rect = element.getBoundingClientRect()
|
||||
const isInViewport = rect.top >= 0 && rect.bottom <= window.innerHeight
|
||||
if (isInViewport && !inViewport) {
|
||||
setInViewport(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', handleScroll)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<>
|
||||
<span className="count-element">{inViewport && <Counter end={end} duration={20} />}</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export default function Preloader() {
|
||||
return (
|
||||
<>
|
||||
<div id="loading" className="loading--theme">
|
||||
<div id="loading-center"><span className="loader" /></div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
const SmoothScroll = () => {
|
||||
useEffect(() => {
|
||||
// Function to handle the smooth scroll behavior
|
||||
const handleClick = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
// Extract the href value from the clicked anchor
|
||||
const href = e.currentTarget.getAttribute('href')
|
||||
|
||||
// Find the element with the corresponding id and scroll into view
|
||||
const targetElement = document.querySelector(href)
|
||||
if (targetElement) {
|
||||
targetElement.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Attach the click event listener to all anchor elements
|
||||
const anchors = document.querySelectorAll('a[href^="#"]')
|
||||
anchors.forEach((anchor) => {
|
||||
anchor.addEventListener('click', handleClick)
|
||||
})
|
||||
|
||||
// Cleanup: remove event listener on component unmount
|
||||
return () => {
|
||||
anchors.forEach((anchor) => {
|
||||
anchor.removeEventListener('click', handleClick)
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
}
|
||||
|
||||
export default SmoothScroll
|
||||
@@ -0,0 +1,27 @@
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
export default function ThemeSwitch() {
|
||||
const [togglETHeme, setTogglETHeme] = useState(
|
||||
() => JSON.parse(localStorage.getItem("togglETHeme")) || "light-theme"
|
||||
)
|
||||
useEffect(() => {
|
||||
localStorage.setItem("togglETHeme", JSON.stringify(togglETHeme))
|
||||
document.body.classList.add(togglETHeme)
|
||||
return () => {
|
||||
document.body.classList.remove(togglETHeme)
|
||||
}
|
||||
}, [togglETHeme])
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className="switcher__tab"
|
||||
onClick={() => togglETHeme === "light-theme" ? setTogglETHeme("dark-theme") : setTogglETHeme("light-theme")
|
||||
}
|
||||
>
|
||||
<span className="switcher__btn light-mode"><i className="flaticon-sun" /></span>
|
||||
<span className="switcher__mode" />
|
||||
<span className="switcher__btn dark-mode"><i className="flaticon-moon" /></span>
|
||||
</nav>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useState } from 'react'
|
||||
import ModalVideo from 'react-modal-video'
|
||||
import "../../node_modules/react-modal-video/css/modal-video.css"
|
||||
|
||||
|
||||
export default function VideoPopup({ style }) {
|
||||
const [isOpen, setOpen] = useState(false)
|
||||
return (
|
||||
<>
|
||||
|
||||
{style === 1 &&
|
||||
// <a className="video-popup1" onClick={() => setOpen(true)}>
|
||||
// <div className="video-btn play-icon-tra">
|
||||
// <div className="video-block-wrapper">
|
||||
// <i className="fas fa-play" />
|
||||
// </div>
|
||||
// </div>
|
||||
// </a>
|
||||
<a className="video-popup1" onClick={() => setOpen(true)}>
|
||||
<div className="video-btn video-btn-xl bg--theme">
|
||||
<div className="video-block-wrapper"><span className="flaticon-play-button" /></div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
{style === 2 &&
|
||||
<a className="video-popup2" onClick={() => setOpen(true)}>
|
||||
<div className="video-btn video-btn-xl bg--theme">
|
||||
<div className="video-block-wrapper"><span className="flaticon-play-button" /></div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
{style === 3 &&
|
||||
|
||||
<a onClick={() => setOpen(true)} className="video-popup2 btn r-04 btn--tra-black hover--violet-100">See how it works
|
||||
</a>
|
||||
}
|
||||
{style === 4 &&
|
||||
<a onClick={() => setOpen(true)} className="video-popup2 btn r-04 btn--theme hover--tra-black ico-20 ico-right">See how it works <span className="flaticon-play" />
|
||||
</a>
|
||||
}
|
||||
{style === 5 &&
|
||||
<a onClick={() => setOpen(true)} className="video-popup2 btn r-04 btn--tra-black hover--theme ico-20 ico-right">
|
||||
See how it works <span className="flaticon-play" />
|
||||
</a>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ModalVideo channel='youtube' autoplay isOpen={isOpen} videoId="vfhzo499OeA" onClose={() => setOpen(false)} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user