Testimonials Slider

Show testimonials

faqlist
import React from 'react';
import { StyleSheet } from 'react-native';
import { Flexbox, Icon, Text, Image, Box } from '@evlop/native-components';

export default function TestimonialCard({ data }: NativeAppBlockProps) {
  // When used inside iterate with itemAs: "testimonial", the item will be available as data.testimonial
  const testimonial = data?.testimonial || {};
  const user = testimonial.user || { name: '', description: '', image: '' };
  const rating = Number(testimonial.rating) || 5;
  const avatarSrc =
    user.image || `https://u"50%"com/api/?size=512&name=${encodeURIComponent(user.name || 'User')}`;

  const filledStars = Math.max(0, Math.min(5, Math.round(rating)));

  return (
    <Flexbox
      flexDirection="column"
      alignItems="center"
      justifyContent="flex-start"
      bg="white"
      p="md"
      borderRadius={12}
    >
      {/* Decorative background shapes */}
      <Box
        width={160}
        height={160}
        borderRadius="50%"
        // bg="rgba(99, 102, 241, 0.08)"
        bg="purple-100"
        style={styles.decoration1}
      />

      <Box
        width={120}
        height={120}
        borderRadius="50%"
        bg="pink-100"
        style={styles.decoration2}
      />

      {/* Content wrapper to ensure content appears above decorations */}
      <Flexbox
        flexDirection="column"
        alignItems="center"
        justifyContent="flex-start"
        width="100%"
        style={styles.contentWrapper}
      >
        {/* Top Row: Star Rating centered */}
        <Flexbox justifyContent="center" alignItems="center" mt="xs">
          <Flexbox flexDirection="row" alignItems="center">
            {Array.from({ length: 5 }).map((_, i) => (
              <Icon
                key={`star-${i}`}
                icon={i < filledStars ? 'ionicons:star' : 'ionicons:star-outline'}
                color={i < filledStars ? '#FFC107' : '#E5E7EB'}
                size={18}
                style={styles.starIcon}
              />
            ))}
          </Flexbox>
        </Flexbox>

        {/* Testimonial title */}
        {testimonial.title ? (
          <>
            <Text mt="sm" fontSize="lg" fontWeight="Bold" color="gray-950" textAlign="center">
              {testimonial.title}
            </Text>
            {/* Decorative accent under title */}
            <Box height={6} width={40} borderRadius={4} mt="2xs" mb="sm" bg="#F59E0B" style={styles.accent} />
          </>
        ) : null}

        {/* Quote and content */}
        <Flexbox alignItems="center" justifyContent="center" mx="sm" mt="sm">
          <Icon size={18} color="#F3F4F6" icon="fontisto:quote-a-right" />
          <Text mx="2xs" mt={3} mb={3} color="gray-900" fontStyle="italic" fontSize="md" textAlign="center" numberOfLines={3}>
            {testimonial.content}
          </Text>
          <Icon size={18} color="#F3F4F6" icon="fontisto:quote-a-left" />
        </Flexbox>

        {/* Decorative dotted line behind divider */}
        <Box height={1} width="100%" my="sm" bg="transparent">
          <Flexbox flexDirection="row" justifyContent="center" alignItems="center" width="100%">
            {Array.from({ length: 15 }).map((_, i) => (
              <Box key={`dot-${i}`} width={6} height={2} bg="gray-100" borderRadius={2} style={styles.dot} />
            ))}
          </Flexbox>
        </Box>

        {/* Bottom Row: User Avatar and Name */}
        <Flexbox justifyContent="center" alignItems="center" width="100%">
          <Box style={styles.avatarWrapper}>
            {/* decorative halo behind avatar */}
            <Box
              width={60}
              height={60}
              borderRadius="50%"
              bg="rgba(59, 130, 246, 0.08)"
              style={styles.avatarHalo}
            />
            <Image src={avatarSrc} size={48} borderRadius="50%" style={styles.avatarImage} />
          </Box>
          <Box ml="sm">
            <Text fontWeight="700" color="gray-900">
              {user.name}
            </Text>
            {user.description ? (
              <Text color="gray-600" fontSize="sm">
                {user.description}
              </Text>
            ) : null}
          </Box>
        </Flexbox>
      </Flexbox>
    </Flexbox>
  );
}

const styles = StyleSheet.create({
  decoration1: {
    position: 'absolute',
    top: -40,
    left: -40,
    transform: [{ rotate: '15deg' }],
    zIndex: 0,
  },
  decoration2: {
    position: 'absolute',
    bottom: -30,
    right: -30,
    transform: [{ rotate: '-20deg' }],
    zIndex: 0,
  },
  contentWrapper: {
    zIndex: 2,
  },
  starIcon: {
    marginHorizontal: 2,
  },
  accent: {
    opacity: 0.12,
  },
  dot: {
    marginHorizontal: 2,
  },
  avatarWrapper: {
    position: 'relative',
  },
  avatarHalo: {
    position: 'absolute',
    left: -6,
    top: -6,
    zIndex: 0,
  },
  avatarImage: {
    zIndex: 1,
  },
});
Loading...