countdown timer upwork v2

by bvotcode

HTML

<div id="container-one"></div>

CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: sans-serif;
}

body {
  min-height: 100vh;
  background: #2f363e;
}

#timer-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 32px;
  margin: 0 auto 1.5rem auto;
}

#timer-wrapper .circle {
  position: relative;
  width: 150px;
  height: 150px;
  display: flex;
  justify-content: center;
  align-items: center;
}

#timer-wrapper .circle svg {
  position: relative;
  width: 150px;
  height: 150px;
  transform: rotate(270deg);
}

#timer-wrapper .circle svg circle {
  width: 100%;
  height: 100%;
  fill: transparent;
  stroke-linecap: round;
  stroke-width: 8;
  stroke: #282828;
  transform: translate(5px, 5px);
}

#timer-wrapper .circle svg circle:nth-child(2) {
  stroke: var(--clr);
  stroke-dasharray: 440;
  stroke-dashoffset: 440;
}

#timer-wrapper div {
  position: absolute;
  text-align: center;
  color: #fff;
  font-weight: 300;
  font-size: 1.5em;
}

#timer-wrapper div span {
  position: absolute;
  transform: translateX(-50%) translateY(0px);
  font-size: 0.35em;
  text-transform: uppercase;
  font-weight: 300;
  letter-spacing: 0.1em;
}

#timer-wrapper .dots {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  z-index: 1000;
}

#timer-wrapper .dots::before {
  content: "";
  position: absolute;
  top: -3px;
  width: 15px;
  height: 15px;
  background: var(--clr);
  border-radius: 50%;
  box-shadow: 0 0 20px var(--clr), 0 0 60px var(--clr);
}

.message-wrapper {
  display: none;
}

.message-wrapper span {
  display: block;
  text-transform: uppercase;
  text-align: center;
  color: #fff;
}

.message-wrapper .title {
  font-size: 4rem;
  line-height: normal;
  font-weight: 600;
}

.message-wrapper .sub-title {
  font-size: 3rem;
  line-height: normal;
  font-weight: 500;
}

JavaScript

class CountdownTimer {
    constructor(containerId, startDate, endDate, title, subtitle) {
        this.startDate = new Date(startDate).getTime();
        this.endDate = new Date(endDate).getTime();
        this.container = document.getElementById(containerId);

        // Dynamically create and append required HTML elements
        this.createHTMLStructure(title, subtitle);

        this.timerContainer = this.container.querySelector('#timer-wrapper');
        this.startMessageContainer = this.container.querySelector('.start-message-wrapper');
        this.endMessageContainer = this.container.querySelector('.end-message-wrapper');
        this.daysElement = this.container.querySelector('#days');
        this.hoursElement = this.container.querySelector('#hours');
        this.minutesElement = this.container.querySelector('#minutes');
        this.secondsElement = this.container.querySelector('#seconds');
        this.daysStroke = this.container.querySelector('#dd');
        this.hoursStroke = this.container.querySelector('#hh');
        this.minutesStroke = this.container.querySelector('#mm');
        this.secondsStroke = this.container.querySelector('#ss');
        this.dayDot = this.container.querySelector('.day_dot');
        this.hourDot = this.container.querySelector('.hr_dot');
        this.minuteDot = this.container.querySelector('.min_dot');
        this.secondDot = this.container.querySelector('.sec_dot');

        this.previousDays = null;
        this.previousHours = null;
        this.previousMinutes = null;
        this.previousSeconds = null;

        this.countdownInterval = setInterval(() => this.updateCountdown(), 1000);
        this.updateCountdown();  // Initial call to set the correct initial state
    }

    createHTMLStructure(title, subtitle) {
        const htmlContent = `
            <div id="timer-wrapper">
                <div class="day-circle circle" style="--clr: #ff2972">
                    <div class="dots day_dot"></div>
         ...