From 16a14ab8285efc116384776e55f38a5260e05080 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <git@imaniti.org>
Date: Mon, 10 Apr 2023 16:40:30 +0200
Subject: [PATCH] add personal calendars

---
 package-lock.json                             | 155 +++++++++++++++++-
 package.json                                  |   8 +-
 source/_data/data.json                        |   1 +
 .../person-calendar.mustache                  |   4 +
 .../03-templates/candidate-detail.mustache    |   8 +-
 source/css/atoms/person-calendar.pcss         |  58 +++++++
 source/css/style.pcss                         |   1 +
 .../components/person_calendar/Calendar.vue   |  29 ++++
 source/js/main.js                             |   4 +-
 9 files changed, 255 insertions(+), 13 deletions(-)
 create mode 100644 source/_patterns/00-atoms/18-person-calendars/person-calendar.mustache
 create mode 100644 source/css/atoms/person-calendar.pcss
 create mode 100644 source/js/components/person_calendar/Calendar.vue

diff --git a/package-lock.json b/package-lock.json
index 84d7f6c..31c489f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,10 @@
       "hasInstallScript": true,
       "license": "MIT",
       "dependencies": {
+        "@fullcalendar/core": "^6.1.5",
+        "@fullcalendar/daygrid": "^6.1.5",
+        "@fullcalendar/interaction": "^6.1.5",
+        "@fullcalendar/vue": "^6.1.5",
         "browser-sync": "^2.26.7",
         "gulp": "^4.0.2",
         "kind-of": "^6.0.3",
@@ -19,7 +23,7 @@
         "styleguidekit-assets-default": "^3.0.0",
         "styleguidekit-mustache-default": "^3.0.0",
         "tailwindcss-elevation": "^0.3.4",
-        "vue": "^2.6.11",
+        "vue": "^2.7.14",
         "vue2-flip-countdown": "^0.10.0"
       },
       "devDependencies": {
@@ -52,7 +56,7 @@
         "tailwindcss-typography": "^3.1.0",
         "vinyl-buffer": "^1.0.1",
         "vinyl-source-stream": "^2.0.0",
-        "vue-template-compiler": "^2.6.11"
+        "vue-template-compiler": "^2.7.14"
       },
       "engines": {
         "node": ">=5.0"
@@ -122,6 +126,17 @@
         "node": ">=4"
       }
     },
+    "node_modules/@babel/parser": {
+      "version": "7.21.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
+      "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==",
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
     "node_modules/@csstools/convert-colors": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
@@ -131,6 +146,39 @@
         "node": ">=4.0.0"
       }
     },
+    "node_modules/@fullcalendar/core": {
+      "version": "6.1.5",
+      "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.5.tgz",
+      "integrity": "sha512-U3ZJy1JGAgvyXG4iLWvTW4osbkt5Fj9gmbU1B+RyRhiqwXGE0F329sX7kqLTzj3QI1IPzyq6xnJfWUIsAe7+qw==",
+      "dependencies": {
+        "preact": "~10.12.1"
+      }
+    },
+    "node_modules/@fullcalendar/daygrid": {
+      "version": "6.1.5",
+      "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.5.tgz",
+      "integrity": "sha512-wXQUNPOyEQ1FEHVdtxP/tLcAAGwY4zeFejujhcznhKC751X8voInF+7kFmI7GDTVgX9cd72Muku3c+gHi8ygEQ==",
+      "peerDependencies": {
+        "@fullcalendar/core": "~6.1.5"
+      }
+    },
+    "node_modules/@fullcalendar/interaction": {
+      "version": "6.1.5",
+      "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.5.tgz",
+      "integrity": "sha512-7U+WsysSlgVSkWqyjLnE6dVKUk2I7sGZN0zcadSfvL2e3KzD30BKgz78p6LRayW2Trtyf/7rZEe1k064ELd0+Q==",
+      "peerDependencies": {
+        "@fullcalendar/core": "~6.1.5"
+      }
+    },
+    "node_modules/@fullcalendar/vue": {
+      "version": "6.1.5",
+      "resolved": "https://registry.npmjs.org/@fullcalendar/vue/-/vue-6.1.5.tgz",
+      "integrity": "sha512-wpwn39qIos2LuEVMTfLWsMIkEmuXF+1qZWqGwBp0r7c3H30w77bFmxWK7pAsXx7TSbvtwhsswRsaWj1iI+xISA==",
+      "peerDependencies": {
+        "@fullcalendar/core": "~6.1.5",
+        "vue": "^2.6.12"
+      }
+    },
     "node_modules/@fullhuman/postcss-purgecss": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-1.3.0.tgz",
@@ -390,6 +438,47 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "2.7.14",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.14.tgz",
+      "integrity": "sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==",
+      "dependencies": {
+        "@babel/parser": "^7.18.4",
+        "postcss": "^8.4.14",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-sfc/node_modules/postcss": {
+      "version": "8.4.21",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
+      "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        }
+      ],
+      "dependencies": {
+        "nanoid": "^3.3.4",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.0.2"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/@vue/compiler-sfc/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/@vue/component-compiler": {
       "version": "4.2.3",
       "resolved": "https://registry.npmjs.org/@vue/component-compiler/-/component-compiler-4.2.3.tgz",
@@ -2864,6 +2953,11 @@
         "node": ">=4"
       }
     },
+    "node_modules/csstype": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+      "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+    },
     "node_modules/d": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
@@ -5971,6 +6065,23 @@
       "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
       "optional": true
     },
+    "node_modules/nanoid": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+      "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
     "node_modules/nanomatch": {
       "version": "1.2.13",
       "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -6617,6 +6728,11 @@
       "dev": true,
       "optional": true
     },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
     "node_modules/picomatch": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
@@ -10073,6 +10189,15 @@
         "node": ">=4"
       }
     },
+    "node_modules/preact": {
+      "version": "10.12.1",
+      "resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz",
+      "integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/preact"
+      }
+    },
     "node_modules/prepend-http": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
@@ -11725,6 +11850,14 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/source-map-resolve": {
       "version": "0.5.3",
       "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
@@ -13307,9 +13440,13 @@
       }
     },
     "node_modules/vue": {
-      "version": "2.6.11",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
-      "integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ=="
+      "version": "2.7.14",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.14.tgz",
+      "integrity": "sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==",
+      "dependencies": {
+        "@vue/compiler-sfc": "2.7.14",
+        "csstype": "^3.1.0"
+      }
     },
     "node_modules/vue-runtime-helpers": {
       "version": "1.1.2",
@@ -13318,13 +13455,13 @@
       "dev": true
     },
     "node_modules/vue-template-compiler": {
-      "version": "2.6.11",
-      "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz",
-      "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==",
+      "version": "2.7.14",
+      "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz",
+      "integrity": "sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==",
       "dev": true,
       "dependencies": {
         "de-indent": "^1.0.2",
-        "he": "^1.1.0"
+        "he": "^1.2.0"
       }
     },
     "node_modules/vue-template-es2015-compiler": {
diff --git a/package.json b/package.json
index 2878496..89c582b 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,10 @@
   "description": "The gulp wrapper around patternlab-node core, providing tasks to interact with the core library and move supporting frontend assets.",
   "version": "2.11.0",
   "dependencies": {
+    "@fullcalendar/core": "^6.1.5",
+    "@fullcalendar/daygrid": "^6.1.5",
+    "@fullcalendar/interaction": "^6.1.5",
+    "@fullcalendar/vue": "^6.1.5",
     "browser-sync": "^2.26.7",
     "gulp": "^4.0.2",
     "kind-of": "^6.0.3",
@@ -12,7 +16,7 @@
     "styleguidekit-assets-default": "^3.0.0",
     "styleguidekit-mustache-default": "^3.0.0",
     "tailwindcss-elevation": "^0.3.4",
-    "vue": "^2.6.11",
+    "vue": "^2.7.14",
     "vue2-flip-countdown": "^0.10.0"
   },
   "resolutions": {
@@ -74,6 +78,6 @@
     "tailwindcss-typography": "^3.1.0",
     "vinyl-buffer": "^1.0.1",
     "vinyl-source-stream": "^2.0.0",
-    "vue-template-compiler": "^2.6.11"
+    "vue-template-compiler": "^2.7.14"
   }
 }
diff --git a/source/_data/data.json b/source/_data/data.json
index 8d9b615..19610ea 100644
--- a/source/_data/data.json
+++ b/source/_data/data.json
@@ -101,6 +101,7 @@
     "label": "Název políčka",
     "placeholder": "Placeholder"
   },
+  "personCalendarData": "[{\"title\": \"event 1\", \"date\": \"2023-04-01\", \"url\": \"https://example.com\"}, {\"title\": \"event 2\", \"date\": \"2023-04-10\", \"url\": \"https://example.com\"}]",
   "greyColors": [
     {"cls": "grey-50", "hex": "#f7f7f7", "name": "Grey 50"},
     {"cls": "grey-100", "hex": "#f3f3f3", "name": "Grey 100"},
diff --git a/source/_patterns/00-atoms/18-person-calendars/person-calendar.mustache b/source/_patterns/00-atoms/18-person-calendars/person-calendar.mustache
new file mode 100644
index 0000000..90f0504
--- /dev/null
+++ b/source/_patterns/00-atoms/18-person-calendars/person-calendar.mustache
@@ -0,0 +1,4 @@
+<div class="__js-root">
+  <ui-person-calendar events='{{ personCalendarData }}'></ui-person-calendar>
+</div>
+
diff --git a/source/_patterns/03-templates/candidate-detail.mustache b/source/_patterns/03-templates/candidate-detail.mustache
index b1426aa..682714a 100644
--- a/source/_patterns/03-templates/candidate-detail.mustache
+++ b/source/_patterns/03-templates/candidate-detail.mustache
@@ -11,7 +11,13 @@
   <main>
     <div class="flex flex-col lg:flex-row lg:space-x-8 xl:space-x-16">
       <section class="lg:w-3/5 xl:w-2/3">
-        {{> molecules-content-block(classes: "w-full", noStartHeadline: true) }}
+        <div class="mb-10">
+          {{> molecules-content-block(classes: "w-full", noStartHeadline: true) }}
+        </div>
+        <div>
+          <h2 class="head-alt-md mb-3">Kalendář</h2>
+          {{> atoms-person-calendar() }}
+        </div>
       </section>
       <section class="lg:w-2/5 xl:w-1/3 pt-8 lg:pt-0 order-first lg:order-last candidate-detail__sidebar">
         <div class="container-padding--zero lg:card lg:elevation-10 lg:container-padding--auto">
diff --git a/source/css/atoms/person-calendar.pcss b/source/css/atoms/person-calendar.pcss
new file mode 100644
index 0000000..daef5ea
--- /dev/null
+++ b/source/css/atoms/person-calendar.pcss
@@ -0,0 +1,58 @@
+:root {
+  --fc-button-bg-color: #000;
+  --fc-button-border-color: #000;
+  --fc-button-hover-bg-color: #f9ce05;
+  --fc-button-hover-border-color: #f9ce05;
+  --fc-button-active-bg-color: #f9ce05;
+  --fc-button-active-border-color: #f9ce05;
+  --fc-event-bg-color: #ed9654;
+  --fc-event-border-color: #ed9654;
+  --fc-border-color: #ed9654;
+  --fc-today-bg-color: #ed9654;
+}
+
+.fc {
+  @apply font-condensed;
+}
+
+/* Don't underline only when there is no href attribute defined. */
+.fc .fc-col-header-cell-cushion:not([href]),
+.fc .fc-daygrid-day-number:not([href]) {
+  @apply no-underline;
+}
+
+.fc .fc-col-header-cell {
+  @apply bg-orange-300 p-3 font-alt text-white text-xl capitalize;
+}
+
+.fc .fc-button {
+  @apply font-alt rounded-none px-5 py-2;
+}
+
+.fc .fc-button:hover:not(:disabled),
+.fc .fc-button:active:not(:disabled){
+  @apply text-black;
+}
+
+.fc .fc-event {
+  @apply p-1 rounded-none border-none text-sm;
+}
+
+.fc .fc-toolbar-title,
+.fc .fc-today-button {
+  @apply capitalize;
+}
+
+.fc .fc-daygrid-day-number {
+  @apply font-alt text-3xl text-orange-300;
+}
+
+.fc .fc-day-today .fc-daygrid-day-number {
+  @apply text-white;
+}
+
+.fc .fc-day-today .fc-event {
+  @apply border-white bg-white;
+
+  --fc-event-text-color: #ed9654;
+}
diff --git a/source/css/style.pcss b/source/css/style.pcss
index bac8477..b49c7c6 100644
--- a/source/css/style.pcss
+++ b/source/css/style.pcss
@@ -32,6 +32,7 @@
 @import "./atoms/icons.pcss";
 @import "./atoms/list.pcss";
 @import "./atoms/paragraph.pcss";
+@import "./atoms/person-calendar.pcss";
 @import "./atoms/quotation.pcss";
 @import "./atoms/social-icon.pcss";
 @import "./atoms/super-button.pcss";
diff --git a/source/js/components/person_calendar/Calendar.vue b/source/js/components/person_calendar/Calendar.vue
new file mode 100644
index 0000000..daf0422
--- /dev/null
+++ b/source/js/components/person_calendar/Calendar.vue
@@ -0,0 +1,29 @@
+<script>
+import FullCalendar from "@fullcalendar/vue"
+import dayGridPlugin from "@fullcalendar/daygrid"
+import interactionPlugin from "@fullcalendar/interaction"
+
+export default {
+  components: {
+    FullCalendar // make the <FullCalendar> tag available
+  },
+  props: ["events"],
+  data() {
+    return {
+      calendarOptions: {
+        plugins: [ dayGridPlugin, interactionPlugin ],
+        initialView: "dayGridMonth",
+        locale: "cs",
+        buttonText: {
+          today: "dnes"
+        },
+        events: JSON.parse(this.events)
+      }
+    }
+  }
+}
+</script>
+
+<template>
+  <FullCalendar :options="calendarOptions" />
+</template>
diff --git a/source/js/main.js b/source/js/main.js
index ea79399..275b0ea 100644
--- a/source/js/main.js
+++ b/source/js/main.js
@@ -4,7 +4,8 @@ import { forEachNode } from "./utils";
 
 import Renderer from "./components/calendar/Renderer";
 import DummyProvider from "./components/calendar/DummyProvider";
-import GoogleProvider from "./components/calendar/GoogleProvider";
+import GoogleProvider from "./components/calendar/GoogleProvider"
+import PersonCalendar from "./components/person_calendar/Calendar";
 import RegionMap from "./components/RegionMap";
 import ViewProvider from "./components/ViewProvider";
 import Navbar from "./components/navbar/Navbar";
@@ -17,6 +18,7 @@ import Chart from 'chart.js/auto';
 Vue.component("ui-calendar-renderer", Renderer);
 Vue.component("ui-calendar-dummy-provider", DummyProvider);
 Vue.component("ui-calendar-google-provider", GoogleProvider);
+Vue.component("ui-person-calendar", PersonCalendar);
 Vue.component("ui-region-map", RegionMap);
 Vue.component("ui-view-provider", ViewProvider);
 Vue.component("ui-navbar", Navbar);
-- 
GitLab