Some ignored filles was missing
This commit is contained in:
parent
7db22245e2
commit
fd5ab6bc0d
268 changed files with 31970 additions and 4 deletions
209
wwwroot/js/utils/PositionUtils.js
Normal file
209
wwwroot/js/utils/PositionUtils.js
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
import { TimeFormatter } from './TimeFormatter';
|
||||
/**
|
||||
* PositionUtils - Positioning utilities with dependency injection
|
||||
* Focuses on pixel/position calculations while delegating date operations
|
||||
*
|
||||
* Note: Uses DateService with date-fns for all date/time operations
|
||||
*/
|
||||
export class PositionUtils {
|
||||
constructor(dateService, config) {
|
||||
this.dateService = dateService;
|
||||
this.config = config;
|
||||
}
|
||||
/**
|
||||
* Convert minutes to pixels
|
||||
*/
|
||||
minutesToPixels(minutes) {
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const pixelsPerHour = gridSettings.hourHeight;
|
||||
return (minutes / 60) * pixelsPerHour;
|
||||
}
|
||||
/**
|
||||
* Convert pixels to minutes
|
||||
*/
|
||||
pixelsToMinutes(pixels) {
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const pixelsPerHour = gridSettings.hourHeight;
|
||||
return (pixels / pixelsPerHour) * 60;
|
||||
}
|
||||
/**
|
||||
* Convert time (HH:MM) to pixels from day start using DateService
|
||||
*/
|
||||
timeToPixels(timeString) {
|
||||
const totalMinutes = this.dateService.timeToMinutes(timeString);
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
||||
const minutesFromDayStart = totalMinutes - dayStartMinutes;
|
||||
return this.minutesToPixels(minutesFromDayStart);
|
||||
}
|
||||
/**
|
||||
* Convert Date object to pixels from day start using DateService
|
||||
*/
|
||||
dateToPixels(date) {
|
||||
const totalMinutes = this.dateService.getMinutesSinceMidnight(date);
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
||||
const minutesFromDayStart = totalMinutes - dayStartMinutes;
|
||||
return this.minutesToPixels(minutesFromDayStart);
|
||||
}
|
||||
/**
|
||||
* Convert pixels to time using DateService
|
||||
*/
|
||||
pixelsToTime(pixels) {
|
||||
const minutes = this.pixelsToMinutes(pixels);
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const dayStartMinutes = gridSettings.dayStartHour * 60;
|
||||
const totalMinutes = dayStartMinutes + minutes;
|
||||
return this.dateService.minutesToTime(totalMinutes);
|
||||
}
|
||||
/**
|
||||
* Beregn event position og størrelse
|
||||
*/
|
||||
calculateEventPosition(startTime, endTime) {
|
||||
let startPixels;
|
||||
let endPixels;
|
||||
if (typeof startTime === 'string') {
|
||||
startPixels = this.timeToPixels(startTime);
|
||||
}
|
||||
else {
|
||||
startPixels = this.dateToPixels(startTime);
|
||||
}
|
||||
if (typeof endTime === 'string') {
|
||||
endPixels = this.timeToPixels(endTime);
|
||||
}
|
||||
else {
|
||||
endPixels = this.dateToPixels(endTime);
|
||||
}
|
||||
const height = Math.max(endPixels - startPixels, this.getMinimumEventHeight());
|
||||
const duration = this.pixelsToMinutes(height);
|
||||
return {
|
||||
top: startPixels,
|
||||
height,
|
||||
duration
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Snap position til grid interval
|
||||
*/
|
||||
snapToGrid(pixels) {
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const snapInterval = gridSettings.snapInterval;
|
||||
const snapPixels = this.minutesToPixels(snapInterval);
|
||||
return Math.round(pixels / snapPixels) * snapPixels;
|
||||
}
|
||||
/**
|
||||
* Snap time to interval using DateService
|
||||
*/
|
||||
snapTimeToInterval(timeString) {
|
||||
const totalMinutes = this.dateService.timeToMinutes(timeString);
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const snapInterval = gridSettings.snapInterval;
|
||||
const snappedMinutes = Math.round(totalMinutes / snapInterval) * snapInterval;
|
||||
return this.dateService.minutesToTime(snappedMinutes);
|
||||
}
|
||||
/**
|
||||
* Beregn kolonne position for overlappende events
|
||||
*/
|
||||
calculateColumnPosition(eventIndex, totalColumns, containerWidth) {
|
||||
const columnWidth = containerWidth / totalColumns;
|
||||
const left = eventIndex * columnWidth;
|
||||
// Lav lidt margin mellem kolonnerne
|
||||
const margin = 2;
|
||||
const adjustedWidth = columnWidth - margin;
|
||||
return {
|
||||
left: left + (margin / 2),
|
||||
width: Math.max(adjustedWidth, 50) // Minimum width
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Check om to events overlapper i tid
|
||||
*/
|
||||
eventsOverlap(start1, end1, start2, end2) {
|
||||
const pos1 = this.calculateEventPosition(start1, end1);
|
||||
const pos2 = this.calculateEventPosition(start2, end2);
|
||||
const event1End = pos1.top + pos1.height;
|
||||
const event2End = pos2.top + pos2.height;
|
||||
return !(event1End <= pos2.top || event2End <= pos1.top);
|
||||
}
|
||||
/**
|
||||
* Beregn Y position fra mouse/touch koordinat
|
||||
*/
|
||||
getPositionFromCoordinate(clientY, column) {
|
||||
const relativeY = clientY - column.boundingClientRect.top;
|
||||
// Snap til grid
|
||||
return this.snapToGrid(relativeY);
|
||||
}
|
||||
/**
|
||||
* Valider at tid er inden for arbejdstimer
|
||||
*/
|
||||
isWithinWorkHours(timeString) {
|
||||
const [hours] = timeString.split(':').map(Number);
|
||||
const gridSettings = this.config.gridSettings;
|
||||
return hours >= gridSettings.workStartHour && hours < gridSettings.workEndHour;
|
||||
}
|
||||
/**
|
||||
* Valider at tid er inden for dag grænser
|
||||
*/
|
||||
isWithinDayBounds(timeString) {
|
||||
const [hours] = timeString.split(':').map(Number);
|
||||
const gridSettings = this.config.gridSettings;
|
||||
return hours >= gridSettings.dayStartHour && hours < gridSettings.dayEndHour;
|
||||
}
|
||||
/**
|
||||
* Hent minimum event højde i pixels
|
||||
*/
|
||||
getMinimumEventHeight() {
|
||||
// Minimum 15 minutter
|
||||
return this.minutesToPixels(15);
|
||||
}
|
||||
/**
|
||||
* Hent maksimum event højde i pixels (hele dagen)
|
||||
*/
|
||||
getMaximumEventHeight() {
|
||||
const gridSettings = this.config.gridSettings;
|
||||
const dayDurationHours = gridSettings.dayEndHour - gridSettings.dayStartHour;
|
||||
return dayDurationHours * gridSettings.hourHeight;
|
||||
}
|
||||
/**
|
||||
* Beregn total kalender højde
|
||||
*/
|
||||
getTotalCalendarHeight() {
|
||||
return this.getMaximumEventHeight();
|
||||
}
|
||||
/**
|
||||
* Convert ISO datetime to time string with UTC-to-local conversion
|
||||
*/
|
||||
isoToTimeString(isoString) {
|
||||
const date = new Date(isoString);
|
||||
return TimeFormatter.formatTime(date);
|
||||
}
|
||||
/**
|
||||
* Convert time string to ISO datetime using DateService with timezone handling
|
||||
*/
|
||||
timeStringToIso(timeString, date = new Date()) {
|
||||
const totalMinutes = this.dateService.timeToMinutes(timeString);
|
||||
const newDate = this.dateService.createDateAtTime(date, totalMinutes);
|
||||
return this.dateService.toUTC(newDate);
|
||||
}
|
||||
/**
|
||||
* Calculate event duration using DateService
|
||||
*/
|
||||
calculateDuration(startTime, endTime) {
|
||||
return this.dateService.getDurationMinutes(startTime, endTime);
|
||||
}
|
||||
/**
|
||||
* Format duration to readable text (Danish)
|
||||
*/
|
||||
formatDuration(minutes) {
|
||||
if (minutes < 60) {
|
||||
return `${minutes} min`;
|
||||
}
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const remainingMinutes = minutes % 60;
|
||||
if (remainingMinutes === 0) {
|
||||
return `${hours} time${hours !== 1 ? 'r' : ''}`;
|
||||
}
|
||||
return `${hours}t ${remainingMinutes}m`;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=PositionUtils.js.map
|
||||
Loading…
Add table
Add a link
Reference in a new issue