Add reactive calendar

This commit is contained in:
Laurent
2025-03-03 15:08:01 +01:00
parent 6500581885
commit 93318bdcc6
10 changed files with 2615 additions and 133 deletions

2498
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,11 @@
}, },
"dependencies": { "dependencies": {
"pinia": "^3.0.1", "pinia": "^3.0.1",
"vite-plugin-svgr": "^4.3.0",
"vite-svg-loader": "^5.1.0",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-router": "^4.5.0" "vue-router": "^4.5.0",
"vue-svg-loader": "^0.16.0"
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/node22": "^22.0.0", "@tsconfig/node22": "^22.0.0",

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
<path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
<path d="M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z"/>
</svg>

After

Width:  |  Height:  |  Size: 254 B

View File

@@ -15,4 +15,5 @@
text-decoration: none; text-decoration: none;
font-family: 'Afacad Flux', sans-serif; font-family: 'Afacad Flux', sans-serif;
transition: 0.3s all; transition: 0.3s all;
box-sizing: border-box;
} }

View File

@@ -1,25 +1,133 @@
<script setup lang="ts"> <script setup lang="ts">
import ArrowRight from "@/assets/arrow-right.svg"
import ArrowLeft from "@/assets/arrow-left.svg";
const months = import {ref, onMounted} from "vue";
[{"January":31}, import {Calendar} from "@/models/Calendar.ts";
{"February":28},
{"March":31}, const calendar = new Calendar();
{"April":30},
{"May":31}, const monthYear = ref("");
{"June":30}, const dates = ref([]);
{"July":31},
{"August":31}, onMounted(() => {
{"September":30}, setupCalendar();
{"October":31}, })
{"November":30},
{"December":31}]; function clickPrev(){
dates.value = calendar.datesOfPrevMonth();
updateMonth();
}
function clickNext(){
dates.value = calendar.datesOfNextMonth();
updateMonth();
}
function setupCalendar(){
dates.value = calendar.datesOfToday();
updateMonth();
}
function updateMonth(){
monthYear.value = calendar.getDate();
}
</script> </script>
<template> <template>
<h1>Calendar</h1> <div class="calendar-container">
<div class="month-picker">
<div>{{ monthYear }}</div>
<div class="arrows">
<div @click="clickPrev" class="prevMonth"><ArrowLeft class="arrow-left" /></div>
<div @click="clickNext" class="nextMonth"><ArrowRight class="arrow-right" /></div>
</div>
</div>
<div class="day-names">
<div>M</div>
<div>T</div>
<div>W</div>
<div>T</div>
<div>F</div>
<div>S</div>
<div>S</div>
</div>
<div class="day-picker">
<div v-for="day in dates" :key="day" :class="{'item': day !== null}">
{{ day }}
</div>
</div>
</div>
</template> </template>
<style scoped> <style scoped>
.calendar-container {
display: flex;
flex-direction: column;
justify-content: center;
border: solid 2px;
border-radius: var(--radius);
padding: 0 20px 20px 20px;
}
.month-picker, .day-picker, .day-names {
justify-items: center;
}
.month-picker {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
border-bottom:solid 1px;
padding: 20px;
}
.arrows {
display: flex;
gap: 10px;
}
.arrow-left, .arrow-right {
width: 30px;
border-radius: var(--radius);
padding: 5px 7px 5px 7px;
}
.arrow-left:hover, .arrow-right:hover {
transform: scale(1.2);
background-color: rgb(239,239,239);
}
.day-picker, .day-names {
display: grid;
grid-template-columns: repeat(7, 2fr);
row-gap: 20px;
width: 100%;
}
.day-names {
padding: 20px 0 20px 0;
}
.item
{
text-align: center;
width: 90%;
min-width: 30px;
height: 100%;
border: solid 1px;
border-radius: 5px;
}
.item:hover
{
transform: scale(1.1);
background-color: var(--secondary-color);
}
</style> </style>

70
src/models/Calendar.ts Normal file
View File

@@ -0,0 +1,70 @@
export class Calendar {
private year : number;
private month : number;
private monthsName : string[] = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
public constructor() {
let date = new Date();
this.year = date.getFullYear();
this.month = date.getMonth();
}
public getDate(){
return this.monthsName[this.month] + " " + this.year;
}
public datesOfToday(){
return this.datesOf();
}
public datesOfNextMonth(){
if(this.month+1 > 11){
this.year += 1;
this.month = 0;
} else {
this.month++;
}
return this.datesOf();
}
public datesOfPrevMonth(){
if(this.month-1 < 0){
this.year -= 1;
this.month = 11;
} else {
this.month--;
}
return this.datesOf();
}
private datesOf() {
let dates = [];
let daysInMonth = new Date(this.year, this.month+1, 0).getDate();
let firstDayOfMonth = (new Date(this.year, this.month, 1).getDay() + 6) % 7; // Adjust to start from Monday
for (let i = 0; i < firstDayOfMonth; i++) {
dates.push(null);
}
for (let day = 1; day <= daysInMonth; day++) {
dates.push(day);
}
return dates;
}
}

View File

@@ -5,12 +5,32 @@ import TextBlock from "@/components/TextBlock.vue";
</script> </script>
<template> <template>
<TextBlock> <div class="container">
<h1>Create an event</h1> <TextBlock class="text-block">
<h1>Create an <span class="colored-text">event</span></h1>
</TextBlock> </TextBlock>
<Calendar /> <Calendar class="calendar" />
</div>
</template> </template>
<style scoped> <style scoped>
.container
{
display: flex;
flex-direction: row;
width: 80%;
gap: 10vw;
}
.text-block
{
width: 50%;
}
.calendar
{
width: 45%;
}
</style> </style>

View File

@@ -4,6 +4,7 @@ import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx' import vueJsx from '@vitejs/plugin-vue-jsx'
import vueDevTools from 'vite-plugin-vue-devtools' import vueDevTools from 'vite-plugin-vue-devtools'
import svgLoader from 'vite-svg-loader';
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
@@ -11,6 +12,7 @@ export default defineConfig({
vue(), vue(),
vueJsx(), vueJsx(),
vueDevTools(), vueDevTools(),
svgLoader()
], ],
resolve: { resolve: {
alias: { alias: {