feat(ui): add autoplay to testimonials and display author initials avatar
This commit is contained in:
@@ -1,11 +1,27 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { useState } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import type { Page } from '../../payload-types'
|
import type { Page } from '../../payload-types'
|
||||||
|
|
||||||
type Props = Extract<NonNullable<Page['layout']>[0], { blockType: 'testimonials' }>
|
type Props = Extract<NonNullable<Page['layout']>[0], { blockType: 'testimonials' }>
|
||||||
|
|
||||||
export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
||||||
const [currentIndex, setCurrentIndex] = useState(0)
|
const [currentIndex, setCurrentIndex] = useState(0)
|
||||||
|
const [lastActionTime, setLastActionTime] = useState(Date.now())
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!testimonials || testimonials.length <= 1) return
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setCurrentIndex((prev) => (prev + 1) % testimonials.length)
|
||||||
|
}, 7500)
|
||||||
|
|
||||||
|
return () => clearInterval(interval)
|
||||||
|
}, [testimonials, lastActionTime])
|
||||||
|
|
||||||
|
const handleDotClick = (index: number) => {
|
||||||
|
setCurrentIndex(index)
|
||||||
|
setLastActionTime(Date.now())
|
||||||
|
}
|
||||||
|
|
||||||
if (!testimonials || testimonials.length === 0) return null
|
if (!testimonials || testimonials.length === 0) return null
|
||||||
|
|
||||||
@@ -21,7 +37,9 @@ export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative min-h-[300px] sm:min-h-[240px]">
|
<div className="relative min-h-[300px] sm:min-h-[240px]">
|
||||||
{testimonials.map((t: NonNullable<Props['testimonials']>[0], index: number) => (
|
{testimonials.map((t: NonNullable<Props['testimonials']>[0], index: number) => {
|
||||||
|
const initial = t.author ? t.author.charAt(0).toUpperCase() : ''
|
||||||
|
return (
|
||||||
<div
|
<div
|
||||||
key={t.id || index}
|
key={t.id || index}
|
||||||
className={`absolute inset-0 flex flex-col items-start justify-start transition-opacity duration-1000 ease-in-out ${
|
className={`absolute inset-0 flex flex-col items-start justify-start transition-opacity duration-1000 ease-in-out ${
|
||||||
@@ -32,14 +50,20 @@ export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
|||||||
{t.quote}
|
{t.quote}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-6">
|
||||||
|
<div className="hidden sm:block w-12 h-px bg-accent/60" />
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-12 h-px bg-accent/60" />
|
<div className="w-12 h-12 rounded-full bg-accent text-background font-heading flex items-center justify-center text-xl sm:text-2xl font-bold shrink-0">
|
||||||
|
{initial}
|
||||||
|
</div>
|
||||||
<p className="font-heading font-bold text-lg sm:text-xl text-foreground/80 uppercase tracking-wide">
|
<p className="font-heading font-bold text-lg sm:text-xl text-foreground/80 uppercase tracking-wide">
|
||||||
{t.author}
|
{t.author}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{testimonials.length > 1 && (
|
{testimonials.length > 1 && (
|
||||||
@@ -47,7 +71,7 @@ export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
|||||||
{testimonials.map((_, index) => (
|
{testimonials.map((_, index) => (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => setCurrentIndex(index)}
|
onClick={() => handleDotClick(index)}
|
||||||
className={`w-2 h-2 transition-all ${
|
className={`w-2 h-2 transition-all ${
|
||||||
index === currentIndex ? 'bg-accent w-8' : 'bg-border hover:bg-foreground/30'
|
index === currentIndex ? 'bg-accent w-8' : 'bg-border hover:bg-foreground/30'
|
||||||
}`}
|
}`}
|
||||||
|
|||||||
Reference in New Issue
Block a user