Home

mint @800a7c5fa14e2089b3a51a813e156e5cdf0920bf - refs - log -
-
https://git.jolheiser.com/mint.git
Budget
mint / index.html
- raw -
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
<!DOCTYPE html>
<html lang='en'>

<head>
  <meta charset='utf-8'>
  <script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.18/index.global.min.js'></script>
  <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
  <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
  <script>

    document.addEventListener('DOMContentLoaded', function () {
      const now = new Date();
      var calendarEl = document.getElementById('calendar');
      var calendar = new FullCalendar.Calendar(calendarEl, {
        initialView: 'dayGridMonth',
        headerToolbar: {
          left: 'prev,next today',
          center: 'title',
          right: ''
        },
        selectable: true,
        select: (info) => {
          console.log(info);
          const days = Math.floor(Math.abs(info.end - info.start) / (1000 * 60 * 60 * 24));
          if (days == 1) {
            toast('add transaction', 'info');
            Swal.fire(input());
            return;
          }
          toast('show mini stats for range', 'info');
          const events = calendar.getEvents().filter((event) => {
            const start = event.start;
            const end = event.end || event.start;
            return start < info.end && end >= info.start
          });
          console.log(events);
          const sum = events.reduce((acc, event) => acc + event.extendedProps.amount, 0);
          toast(`\$${sum}`, 'success')
        },
        eventClick: (info) => {
          const event = info.event;
          const props = event.extendedProps;
          Swal.fire(input(event.id, props.title, props.amount, props.recurring));
        },
        eventClassNames: 'cursor-pointer',
        events: [{id: '1', title: 'A bill! ($200)', start: now, allDay: true, extendedProps: {title: 'A bill!', amount: 200, recurring: true}}, {id: '2', title: 'Another bill! ($150)', start: new Date(now.getTime() + (1000 * 60 * 60 * 24 * 2)), allDay: true, extendedProps: {title: 'Another bill!', amount: 150, recurring: false}}],
      });
      calendar.render();
    });

    function toast(message, level = "error", duration = 5) {
      const Toast = Swal.mixin({
        toast: true,
        position: "top-end",
        showConfirmButton: false,
        timer: duration * 1000,
        timerProgressBar: true,
        didOpen: (toast) => {
          toast.addEventListener('click', () => Swal.close());
          toast.onmouseenter = Swal.stopTimer;
          toast.onmouseleave = Swal.resumeTimer;
        }
      });
      Toast.fire({
        icon: level,
        title: message
      });
    }

    function input(id = '', title = 'New Transaction', amount = 0, recurring = true) {
      return {
        title: `<input type="text" class="font-semibold" value="${title}"/>`,
        html: `
          <div class="grid grid-cols-1 gap-x-4 gap-y-3 items-center text-left">
            <input type="hidden" name="id" value="${id}"/>
            <label class="font-semibold">Amount: $<input class="border rounded w-30 mx-px p-1" type="number" name="amount" value="${amount}"/></label>
            <label class="font-semibold">Recurring? <input class="border rounded w-4 h-4" type="checkbox" name="recurring" ${recurring ? "checked" : ""}/></label>
            <div id="recurringOptions" class="${recurring ? "" : "hidden"}">
              <label><input type="radio" name="recurrance"/> Monthly on the 1st</label>
              <br/>
              <label><input type="radio" name="recurrance"/> Every <input class="border rounded w-15 p-1" type="number" min="1" max="4" value="1"/> weeks on Monday</label>
            </div>
          </div>
        `,
        allowOutsideClick: false,
        showCloseButton: true,
        confirmButtonText: 'Save',
        didRender: (swal) => {
          const $recurring = document.querySelector("[name='recurring']");
          const $opts = document.getElementById("recurringOptions");
          $recurring.addEventListener('change', () => {
            $recurring.checked ? $opts.classList.remove('hidden') : $opts.classList.add('hidden');
          });
        }
      }
      return
    }
  </script>
</head>

<body>
  <div id='calendar' class='max-w-[90vw] max-h-[90vh] m-[40px_auto]'></div>
</body>

</html>