Major new version (#2)

Release Notes

Architecture
- Component refactor: removed monoliths (`Calendar.vue`, `CalendarGrid.vue`); expanded granular view + header/control components.
- Dialog system introduced (`BaseDialog`, `SettingsDialog`).

State & Data
- Store redesigned: Map-based events + recurrence map; mutation counters.
- Local persistence + undo/redo history (custom plugins).

Date & Holidays
- Migrated all date logic to `date-fns` (+ tz).
- Added national holiday support (toggle + loading utilities).

Recurrence & Events
- Consolidated recurrence handling; fixes for monthly edge days (29–31), annual, multi‑day, and complex weekly repeats.
- Reliable splitting/moving/resizing/deletion of repeating and multi‑day events.

Interaction & UX
- Double‑tap to create events; improved drag (multi‑day + position retention).
- Scroll & inertial/momentum navigation; year change via numeric scroller.
- Movable event dialog; live settings application.

Performance
- Progressive / virtual week rendering, reduced off‑screen buffer.
- Targeted repaint strategy; minimized full re-renders.

Plugins Added
- History, undo normalization, persistence, scroll manager, virtual weeks.

Styling & Layout
- Responsive + compact layout refinements; header restructured.
- Simplified visual elements (removed dots/overflow text); holiday styling adjustments.

Reliability / Fixes
- Numerous recurrence, deletion, orientation/rotation, and event indexing corrections.
- Cross-browser fallback (Firefox week info).

Dependencies Added
- date-fns, date-fns-tz, date-holidays, pinia-plugin-persistedstate.

Net Change
- 28 files modified; ~4.4K insertions / ~2.2K deletions (major refactor + feature set).
This commit is contained in:
LeoVasanko committed 2025-08-26 03:58:24 +00:00
1 parent 86a06acccb
commit dbe4c99b07
28 files changed
+4465 -2207

No files matched your search

+24 -17
View File
@@ -3,11 +3,13 @@
<div class="week-label">W{{ weekNumber }}</div>
<div class="days-grid">
<DayCell v-for="day in days" :key="day.dateStr" :day="day" />
<div class="week-overlay">
<!-- Event spans will be rendered here -->
</div>
<div class="week-overlay"></div>
</div>
<div v-if="monthLabel" class="month-name-label" :style="{ height: `${monthLabel.weeksSpan * 64}px` }">
<div
v-if="monthLabel"
class="month-name-label"
:style="{ height: `${monthLabel.weeksSpan * 64}px` }"
>
<span>{{ monthLabel.name }} '{{ monthLabel.year }}</span>
</div>
</div>
@@ -16,51 +18,56 @@
<script setup>
import { computed } from 'vue'
import DayCell from './DayCell.vue'
import { isoWeekInfo, toLocalString, getLocalizedMonthName, monthAbbr } from '@/utils/date'
import {
toLocalString,
getLocalizedMonthName,
monthAbbr,
DEFAULT_TZ,
getISOWeek,
} from '@/utils/date'
import { addDays } from 'date-fns'
const props = defineProps({
week: {
type: Object,
required: true
}
required: true,
},
})
const weekNumber = computed(() => {
return isoWeekInfo(props.week.monday).week
})
const weekNumber = computed(() => getISOWeek(props.week.monday))
const days = computed(() => {
const d = new Date(props.week.monday)
const result = []
for (let i = 0; i < 7; i++) {
const dateStr = toLocalString(d)
const dateStr = toLocalString(d, DEFAULT_TZ)
result.push({
date: new Date(d),
dateStr,
dayOfMonth: d.getDate(),
month: d.getMonth(),
isFirstDayOfMonth: d.getDate() === 1,
monthClass: monthAbbr[d.getMonth()]
monthClass: monthAbbr[d.getMonth()],
})
d.setDate(d.getDate() + 1)
d.setTime(addDays(d, 1).getTime())
}
return result
})
const monthLabel = computed(() => {
const firstDayOfMonth = days.value.find(d => d.isFirstDayOfMonth)
const firstDayOfMonth = days.value.find((d) => d.isFirstDayOfMonth)
if (!firstDayOfMonth) return null
const month = firstDayOfMonth.month
const year = firstDayOfMonth.date.getFullYear()
// This is a simplified calculation for weeksSpan
const weeksSpan = 4
const weeksSpan = 4
return {
name: getLocalizedMonthName(month),
year: String(year).slice(-2),
weeksSpan
weeksSpan,
}
})
</script>