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
106
107
108
109
110
111
112
|
diff --git a/index.html b/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..956170504cb7d022e29fd50e43dbf6ea6af40954
--- /dev/null
+++ b/index.html
@@ -0,0 +1,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>
\ No newline at end of file
|