summaryrefslogtreecommitdiff
path: root/packages/frontend/src/widgets/WidgetCalendar.vue
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-01-10 06:08:40 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-01-10 06:08:40 +0900
commit618405c4d39753c1a9135fd0759aff2ecb3a94b3 (patch)
treeb0551494d3ffd37ee3e7f7ad75bc81f54d3fb249 /packages/frontend/src/widgets/WidgetCalendar.vue
parentrefactor(client): use css modules (diff)
downloadmisskey-618405c4d39753c1a9135fd0759aff2ecb3a94b3.tar.gz
misskey-618405c4d39753c1a9135fd0759aff2ecb3a94b3.tar.bz2
misskey-618405c4d39753c1a9135fd0759aff2ecb3a94b3.zip
refactor(client): rename widget filename
Diffstat (limited to 'packages/frontend/src/widgets/WidgetCalendar.vue')
-rw-r--r--packages/frontend/src/widgets/WidgetCalendar.vue214
1 files changed, 214 insertions, 0 deletions
diff --git a/packages/frontend/src/widgets/WidgetCalendar.vue b/packages/frontend/src/widgets/WidgetCalendar.vue
new file mode 100644
index 0000000000..1bd431259a
--- /dev/null
+++ b/packages/frontend/src/widgets/WidgetCalendar.vue
@@ -0,0 +1,214 @@
+<template>
+<div class="mkw-calendar" :class="{ _panel: !widgetProps.transparent }">
+ <div class="calendar" :class="{ isHoliday }">
+ <p class="month-and-year">
+ <span class="year">{{ $t('yearX', { year }) }}</span>
+ <span class="month">{{ $t('monthX', { month }) }}</span>
+ </p>
+ <p v-if="month === 1 && day === 1" class="day">🎉{{ $t('dayX', { day }) }}<span style="display: inline-block; transform: scaleX(-1);">🎉</span></p>
+ <p v-else class="day">{{ $t('dayX', { day }) }}</p>
+ <p class="week-day">{{ weekDay }}</p>
+ </div>
+ <div class="info">
+ <div>
+ <p>{{ i18n.ts.today }}<b>{{ dayP.toFixed(1) }}%</b></p>
+ <div class="meter">
+ <div class="val" :style="{ width: `${dayP}%` }"></div>
+ </div>
+ </div>
+ <div>
+ <p>{{ i18n.ts.thisMonth }}<b>{{ monthP.toFixed(1) }}%</b></p>
+ <div class="meter">
+ <div class="val" :style="{ width: `${monthP}%` }"></div>
+ </div>
+ </div>
+ <div>
+ <p>{{ i18n.ts.thisYear }}<b>{{ yearP.toFixed(1) }}%</b></p>
+ <div class="meter">
+ <div class="val" :style="{ width: `${yearP}%` }"></div>
+ </div>
+ </div>
+ </div>
+</div>
+</template>
+
+<script lang="ts" setup>
+import { onUnmounted, ref } from 'vue';
+import { useWidgetPropsManager, Widget, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget';
+import { GetFormResultType } from '@/scripts/form';
+import { i18n } from '@/i18n';
+import { useInterval } from '@/scripts/use-interval';
+
+const name = 'calendar';
+
+const widgetPropsDef = {
+ transparent: {
+ type: 'boolean' as const,
+ default: false,
+ },
+};
+
+type WidgetProps = GetFormResultType<typeof widgetPropsDef>;
+
+// 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない
+//const props = defineProps<WidgetComponentProps<WidgetProps>>();
+//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
+const props = defineProps<{ widget?: Widget<WidgetProps>; }>();
+const emit = defineEmits<{ (ev: 'updateProps', props: WidgetProps); }>();
+
+const { widgetProps, configure } = useWidgetPropsManager(name,
+ widgetPropsDef,
+ props,
+ emit,
+);
+
+const year = ref(0);
+const month = ref(0);
+const day = ref(0);
+const weekDay = ref('');
+const yearP = ref(0);
+const monthP = ref(0);
+const dayP = ref(0);
+const isHoliday = ref(false);
+const tick = () => {
+ const now = new Date();
+ const nd = now.getDate();
+ const nm = now.getMonth();
+ const ny = now.getFullYear();
+
+ year.value = ny;
+ month.value = nm + 1;
+ day.value = nd;
+ weekDay.value = [
+ i18n.ts._weekday.sunday,
+ i18n.ts._weekday.monday,
+ i18n.ts._weekday.tuesday,
+ i18n.ts._weekday.wednesday,
+ i18n.ts._weekday.thursday,
+ i18n.ts._weekday.friday,
+ i18n.ts._weekday.saturday,
+ ][now.getDay()];
+
+ const dayNumer = now.getTime() - new Date(ny, nm, nd).getTime();
+ const dayDenom = 1000/*ms*/ * 60/*s*/ * 60/*m*/ * 24/*h*/;
+ const monthNumer = now.getTime() - new Date(ny, nm, 1).getTime();
+ const monthDenom = new Date(ny, nm + 1, 1).getTime() - new Date(ny, nm, 1).getTime();
+ const yearNumer = now.getTime() - new Date(ny, 0, 1).getTime();
+ const yearDenom = new Date(ny + 1, 0, 1).getTime() - new Date(ny, 0, 1).getTime();
+
+ dayP.value = dayNumer / dayDenom * 100;
+ monthP.value = monthNumer / monthDenom * 100;
+ yearP.value = yearNumer / yearDenom * 100;
+
+ isHoliday.value = now.getDay() === 0 || now.getDay() === 6;
+};
+
+useInterval(tick, 1000, {
+ immediate: true,
+ afterMounted: false,
+});
+
+defineExpose<WidgetComponentExpose>({
+ name,
+ configure,
+ id: props.widget ? props.widget.id : null,
+});
+</script>
+
+<style lang="scss" scoped>
+.mkw-calendar {
+ padding: 16px 0;
+
+ &:after {
+ content: "";
+ display: block;
+ clear: both;
+ }
+
+ > .calendar {
+ float: left;
+ width: 60%;
+ text-align: center;
+
+ &.isHoliday {
+ > .day {
+ color: #ef95a0;
+ }
+ }
+
+ > .month-and-year, > .week-day {
+ margin: 0;
+ line-height: 18px;
+ font-size: 0.9em;
+
+ > .year, > .month {
+ margin: 0 4px;
+ }
+ }
+
+ > .day {
+ margin: 10px 0;
+ line-height: 32px;
+ font-size: 1.75em;
+ }
+ }
+
+ > .info {
+ display: block;
+ float: left;
+ width: 40%;
+ padding: 0 16px 0 0;
+ box-sizing: border-box;
+
+ > div {
+ margin-bottom: 8px;
+
+ &:last-child {
+ margin-bottom: 4px;
+ }
+
+ > p {
+ display: flex;
+ margin: 0 0 2px 0;
+ font-size: 0.75em;
+ line-height: 18px;
+ opacity: 0.8;
+
+ > b {
+ margin-left: auto;
+ }
+ }
+
+ > .meter {
+ width: 100%;
+ overflow: hidden;
+ background: var(--X11);
+ border-radius: 8px;
+
+ > .val {
+ height: 4px;
+ transition: width .3s cubic-bezier(0.23, 1, 0.32, 1);
+ }
+ }
+
+ &:nth-child(1) {
+ > .meter > .val {
+ background: #f7796c;
+ }
+ }
+
+ &:nth-child(2) {
+ > .meter > .val {
+ background: #a1de41;
+ }
+ }
+
+ &:nth-child(3) {
+ > .meter > .val {
+ background: #41ddde;
+ }
+ }
+ }
+ }
+}
+</style>