How to use Custom Dynamic Calendar in Vue 3

Use Vue.js Dynamic Calendar. Without Any npm Plugin And jQuery.

 

Step 1: Components

<template>
  <div class="calendar-area">
    <div class="container">
      <div class="calendar-wrapper">
        <header>
          <h3>Calendar</h3>
          <p class="current-date">{{ currentDate }}</p>
          <div class="icons">
            <span id="prev" @click="changeMonth(-1)">
              <i class="ri-arrow-left-s-line"></i>
            </span>
            <span id="next" @click="changeMonth(1)">
              <i class="ri-arrow-right-s-line"></i>
            </span>
          </div>
        </header>
        <div class="calendar">
          <ul class="weeks">
            <li>Sun</li>
            <li>Mon</li>
            <li>Tue</li>
            <li>Wed</li>
            <li>Thu</li>
            <li>Fri</li>
            <li>Sat</li>
          </ul>
          <ul class="days">
            <li
              v-for="(day, index) in calendarDays"
              :key="index"
              :class="[day.class]"
            >
              {{ day.date }}
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

Step 2: Script

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "GetAnAppointment",
  data() {
    const date = new Date();
    const currYear = date.getFullYear();
    const currMonth = date.getMonth();

    return {
      currentDate: "",
      currYear,
      currMonth,
      months: [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
      ] as string[],
    };
  },
  computed: {
    calendarDays() {
      const date = new Date();
      const currDate = date.getDate();
      const currMonth = date.getMonth();
      const currYear = date.getFullYear();
      const firstDayOfMonth = new Date(
        this.currYear,
        this.currMonth,
        1
      ).getDay();
      const lastDateOfMonth = new Date(
        this.currYear,
        this.currMonth + 1,
        0
      ).getDate();
      const lastDayOfMonth = new Date(
        this.currYear,
        this.currMonth,
        lastDateOfMonth
      ).getDay();
      const lastDateOfLastMonth = new Date(
        this.currYear,
        this.currMonth,
        0
      ).getDate();
      const days: { date: number; class: string }[] = [];

      for (let i = firstDayOfMonth; i > 0; i--) {
        const date = lastDateOfLastMonth - i + 1;
        days.push({ date, class: "inactive" });
      }

      for (let i = 1; i <= lastDateOfMonth; i++) {
        const isToday =
          i === currDate &&
          this.currMonth === currMonth &&
          this.currYear === currYear;
        days.push({ date: i, class: isToday ? "active" : "" });
      }

      for (let i = lastDayOfMonth; i < 6; i++) {
        const date = i - lastDayOfMonth + 1;
        days.push({ date, class: "inactive" });
      }

      return days;
    },
  },
  mounted() {
    this.currentDate = `${this.months[this.currMonth]} ${this.currYear}`;
  },
  methods: {
    changeMonth(direction: number) {
      this.currMonth += direction;

      if (this.currMonth < 0 || this.currMonth > 11) {
        const date = new Date(
          this.currYear,
          this.currMonth,
          new Date().getDate()
        );
        this.currYear = date.getFullYear();
        this.currMonth = date.getMonth();
      }

      this.currentDate = `${this.months[this.currMonth]} ${this.currYear}`;
    },
  },
});
</script>

Step 3: SCSS

<style lang="scss" scoped>
.calendar-wrapper {
  background: var(--whiteColor);
  border-radius: 20px;
  border-left: 5px solid #dfedee;
  border-bottom: 5px solid #dfedee;
  margin-left: 50px;

  header {
    display: flex;
    align-items: center;
    padding: 35px 20px 30px;
    justify-content: space-between;

    h3 {
      margin-bottom: 0;
      font-size: 20px;
      font-weight: bold;
    }
    .icons {
      display: flex;

      span {
        display: inline-block;
        height: 30px;
        width: 30px;
        line-height: 30px;
        margin: 0 2px;
        cursor: pointer;
        background-color: #f3f3f3;
        color: var(--blackColor);
        text-align: center;
        font-size: 22px;
        border-radius: 50%;
        transition: var(--transition);

        &:hover {
          background: var(--secondaryColor);
          color: var(--whiteColor);
        }
      }
    }
    .current-date {
      font-size: 18px;
      margin: {
        left: 40px;
        bottom: 0;
      }
    }
  }
  .calendar {
    padding: 0 20px 35px 20px;

    ul {
      display: flex;
      flex-wrap: wrap;
      list-style: none;
      text-align: center;

      li {
        color: var(--paragraphColor);
        width: calc(100% / 7);
        font-size: 1.07rem;
      }
    }
    .weeks {
      padding-left: 0;
      background: #ecf4fa;
      padding: 20px 15px;
      margin-bottom: 0;

      li {
        font-weight: 500;
        cursor: default;
        color: var(--blackColor);
        font-weight: 500;
        font-family: var(--heading-fontFamily);
        font-size: 15px;
      }
    }
    .days {
      padding-left: 12px;
      margin-bottom: 0;

      li {
        font-family: var(--heading-fontFamily);
        color: var(--paragraphColor);
        font-weight: 400;
        z-index: 1;
        cursor: pointer;
        position: relative;
        margin-top: 25px;
        transition: var(--transition);

        &.inactive {
          color: #8896a4;
        }
        &.active {
          color: var(--whiteColor);

          &::before {
            background: var(--secondaryColor);
          }
        }
        &::before {
          position: absolute;
          content: "";
          left: 50%;
          top: 50%;
          height: 30px;
          width: 30px;
          line-height: 30px;
          z-index: -1;
          border-radius: 2px;
          transform: translate(-50%, -55%);
        }
        &:not(.active):hover::before {
          background: #f2f2f2;
        }
      }
    }
  }
}

/* Max width 767px */
@media only screen and (max-width: 767px) {
  .calendar-wrapper {
    margin-left: 0;

    header {
      padding: 25px 10px 20px;
      display: block;

      .current-date {
        margin: {
          top: 10px;
          bottom: 10px;
          left: 0;
        }
      }
    }
    .calendar {
      padding: 0 10px 20px 10px;

      .weeks {
        padding: 18px 10px;
      }
    }
  }
}

/* Min width 576px to Max width 767px */
@media only screen and (min-width: 576px) and (max-width: 767px) {
  .calendar-wrapper {
    header {
      display: flex !important;
    }
  }
}

/* Min width 768px to Max width 991px */
@media only screen and (min-width: 768px) and (max-width: 991px) {
  .calendar-wrapper {
    margin-left: 0;
  }
}

/* Min width 992px to Max width 1199px */
@media only screen and (min-width: 992px) and (max-width: 1199px) {
  .calendar-wrapper {
    margin-left: 0;
  }
}

/* Min width 1200px to Max width 1399px */
@media only screen and (min-width: 1200px) and (max-width: 1399px) {
  .calendar-wrapper {
    header {
      h3 {
        font-size: 15px;
      }
      .current-date {
        font-size: 14px;
        margin-left: 20px;
      }
    }
  }
}
</style>

 


Posted

in

, , ,

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *