Countdown timer

Product details display

import React, { useState, useEffect } from 'react';
import { Flexbox, Text } from '@evlop/native-components';

function Digit({ char, textStyle }) {
  const fontSize = (textStyle && textStyle.fontSize) || 18;

  return (
    <Text color={textStyle.color} fontSize={fontSize} fontWeight={textStyle.fontWeight} style={{ lineHeight: fontSize * 1.25, textAlign: 'center' }}>
      {char}
    </Text>
  );
}

function StaticNumber({ value, textStyle = {} }) {
  const str = String(value);
  return (
    <Flexbox flexDirection="row" alignItems="center">
      {str.split('').map((ch, idx) => (
        <Digit key={idx} char={ch} textStyle={textStyle} />
      ))}
    </Flexbox>
  );
}

// The component now accepts a `data` prop (provided by the builder). Make the countdown configurable
const Countdown:AppBlock =function ({ data = {} }) {
  const [timeLeft, setTimeLeft] = useState({});

  const targetDateString = data.targetDate || '2026-01-01T00:00:00';
  const target = new Date(targetDateString);

  const calculateTimeLeft = () => {
    const now = new Date();
    const difference = +target - +now;

    if (difference <= 0) return { days: 0, hours: 0, minutes: 0, seconds: 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),
    };
  };

  useEffect(() => {
    setTimeLeft(calculateTimeLeft());
    const id = setInterval(() => setTimeLeft(calculateTimeLeft()), 1000);
    return () => clearInterval(id);
    // target may change via data prop — update when it does
  }, [targetDateString]);

  const formatNumber = (n) => String(n).padStart(2, '0');

  const intervals = [
    { key: 'days', label: 'DAYS' },
    { key: 'hours', label: 'HOURS' },
    { key: 'minutes', label: 'MIN' },
    { key: 'seconds', label: 'SEC' },
  ];

  // colorful palette for timer blocks (kept default but could be exposed later)
  const timerColors = ['#FFEDD5', '#EDE9FE', '#DBEAFE', '#ECFCCB'];
  const timerTextColors = ['#9A3412', '#5B21B6', '#1E40AF', '#365314'];

  const showLabels = data.showLabels !== undefined ? Boolean(data.showLabels) : true;

  const timerComponents = intervals.map((it, idx) => (
    <Flexbox
      key={it.key}
      bg={timerColors[idx % timerColors.length]}
      p="xs"
      borderRadius={10}
      alignItems="center"
      justifyContent="center"
      flexDirection="column"
      style={{ minWidth: 56, marginHorizontal: 6, shadowColor: '#000', shadowOpacity: 0.03, shadowRadius: 6 }}
    >
      <StaticNumber value={formatNumber(timeLeft[it.key] ?? 0)} textStyle={{ color: timerTextColors[idx % timerTextColors.length], fontSize: 16, fontWeight: '800' }} />
      {showLabels && <Text color="#475569" fontSize="xs">{it.label}</Text>}
    </Flexbox>
  ));

  const title = data.title || 'Countdown to 2026';
  const subtitle = data.subtitle || 'A colorful countdown.';

  return (
    <Flexbox
      bg="#fff7ed"
      p="xl"
      gap={20}
      flexDirection="column"
      alignItems="center"
      justifyContent="center"
      style={{ flex: 1 }}
    >
      <Flexbox
        bg="white"
        borderRadius={16}
        p="lg"
        gap={12}
        flexDirection="column"
        alignItems="center"
        style={{ width: '100%', maxWidth: 720, elevation: 3 }}
      >
        {/* colorful stripe */}
        <Flexbox flexDirection="row" style={{ width: '100%', height: 8, borderRadius: 8, overflow: 'hidden' }}>
          <Flexbox bg="#FB7185" style={{ flex: 1 }} />
          <Flexbox bg="#F59E0B" style={{ flex: 1 }} />
          <Flexbox bg="#10B981" style={{ flex: 1 }} />
          <Flexbox bg="#7C3AED" style={{ flex: 1 }} />
        </Flexbox>

        <Text color="#6D28D9" fontSize="2xl" fontWeight="bold">{title}</Text>
        <Text color="#374151" fontSize="sm">{subtitle}</Text>

        <Flexbox flexDirection="row" alignItems="center" justifyContent="center" style={{ width: '100%', flexWrap: 'nowrap' }}>
          {timerComponents}
        </Flexbox>
      </Flexbox>
    </Flexbox>
  );
}

export default Countdown;
Loading...