Two month of work

This commit is contained in:
2026-02-17 10:35:03 +01:00
parent 0ffbeeedff
commit d9fd3d1ccb
158 changed files with 5637 additions and 1512 deletions
+184 -73
View File
@@ -3,10 +3,40 @@ import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
import { toast } from 'vue-sonner'
// -----------------------------------------------------------------------------
// Attributes, classes
// -----------------------------------------------------------------------------
// #region Clöasses
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
const randomColors = [
'bg-rose-200 dark:bg-rose-700',
'bg-lime-200 dark:bg-lime-700',
'bg-orange-200 dark:bg-orange-700',
'bg-sky-200 dark:bg-sky-700',
'bg-amber-200 dark:bg-amber-700',
'bg-blue-200 dark:bg-blue-700',
'bg-purple-200 dark:bg-purple-700'
]
export function bgColorForString(input: string): string {
let charCodeSum = 0;
for (let i = 0; i < input.length; i++) {
charCodeSum += input.charCodeAt(i)
}
return randomColors[charCodeSum % randomColors.length];
}
// -----------------------------------------------------------------------------
// URLs
// -----------------------------------------------------------------------------
export function urlIsActive(urlToCheck: NonNullable<InertiaLinkProps['href']>, currentUrl: string) {
return currentUrl.indexOf(toUrl(urlToCheck)) >= 0
}
@@ -16,6 +46,25 @@ export function toUrl(href: NonNullable<InertiaLinkProps['href']>) {
}
// -----------------------------------------------------------------------------
// Number helpers and formatting
// -----------------------------------------------------------------------------
export function toFixedRounded(num: number, precision: number): number {
return Number((Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision)).toFixed(precision))
}
export function randomInt(max: number) {
return Math.floor(Math.random() * max);
}
export function isNumeric(value: any) {
return !isNaN(parseFloat(value))
}
// Currency
const currencyFormatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR',
@@ -39,86 +88,122 @@ export function toRoundedCurrency(value: number | undefined) {
return roundedCurrencyFormatter.format(toFixedRounded(value, 0));
}
export function toFixedRounded(num: number, precision: number): number {
return Number((Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision)).toFixed(precision))
// Dates
const locale = "de-De"
const closeDaysThreshhold = 2
const rtf = new Intl.RelativeTimeFormat(locale, {
numeric: "auto", // "always" | "auto"
style: "long", // "long" | "short" | "narrow"
});
export function isToday(value: string | Date): boolean {
return daysFromNow(value) === 0
}
export function isBefore(value: string | Date, comparison: string | Date): boolean {
let date = (typeof value === 'string') ? new Date(value) : value
let comparisonDate = (typeof comparison === 'string') ? new Date(comparison) : comparison
return date.getTime() < comparisonDate.getTime()
}
export function isAfter(value: string | Date, comparison: string | Date) {
let date = (typeof value === 'string') ? new Date(value) : value
let comparisonDate = (typeof comparison === 'string') ? new Date(comparison) : comparison
return date.getTime() > comparisonDate.getTime()
}
export function millisFromNow(value: string | Date): number {
let date = (typeof value === 'string') ? new Date(value) : value
return date.getTime() - new Date().getTime()
}
export function minutesFromNow(value: string | Date): number {
return Math.round(millisFromNow(value) / (1000 * 60))
}
export function hoursFromNow(value: string | Date): number {
return Math.round(millisFromNow(value) / (1000 * 60 * 60))
}
export function daysFromNow(value: string | Date): number {
return Math.round(millisFromNow(value) / (1000 * 60 * 60 * 24))
}
export function isThisHour(value: Date | string): boolean {
if (!isToday(value)) return false
return Math.abs(hoursFromNow(value)) <= 1
}
export function isCloseDays(value: Date | string): boolean {
return Math.abs(daysFromNow(value)) <= closeDaysThreshhold
}
export function isSoon(value: Date | string): boolean {
const days = daysFromNow(value)
return days > 0 && days <= closeDaysThreshhold
}
export function isThisYear(value: Date | string): boolean {
return new Date().getFullYear() == new Date(value).getFullYear()
}
export function toDuration(value: string | Date): string {
if (isThisHour(value)) return rtf.format(minutesFromNow(value), 'minute')
else if (isCloseDays(value)) return rtf.format(daysFromNow(value), 'day')
else if (isThisYear(value)) return toShortLocalDate(value)
else return toLocalDate(value)
}
export function toLocalDate(value: string | Date) {
const date = new Date(value);
return date.toLocaleDateString('de-DE', { day: '2-digit', month: 'short', year: 'numeric' });
// return date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
// return date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: '2-digit' });
let date = (typeof value === 'string') ? new Date(value) : value
return date.toLocaleDateString(locale, { day: '2-digit', month: 'short', year: 'numeric' });
}
export function toShortISOString(date: Date | string) {
let tempDate = (typeof date === 'string') ? new Date(date) : date
return tempDate.toISOString().split('T')[0]
export function toShortLocalDate(value: string | Date) {
let date = (typeof value === 'string') ? new Date(value) : value
return date.toLocaleDateString(locale, { day: 'numeric', month: 'short' });
}
export function calcDueDate(date: Date, daysAfterInvoice: number): Date {
export function toShortISOString(value: Date | string) {
let date = (typeof value === 'string') ? new Date(value) : value
return date.toISOString().split('T')[0]
}
export function toDatetimeLocal(value: Date | string) {
let date = (typeof value === 'string') ? new Date(value) : value
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day}T${hours}:${minutes}`;
}
export function calcDueDate(date: Date | string, daysAfterInvoice: number): Date {
let dueDate = new Date(date);
dueDate.setDate(date.getDate() + daysAfterInvoice);
dueDate.setDate(dueDate.getDate() + daysAfterInvoice);
return dueDate;
}
export function randomInt(max: number) {
return Math.floor(Math.random() * max);
export function randomDate(): Date {
let date = new Date()
date.setDate(date.getDate() - Math.random() * 20)
return date
}
const randomColors = [
'bg-rose-200 dark:bg-rose-700',
'bg-lime-200 dark:bg-lime-700',
'bg-orange-200 dark:bg-orange-700',
'bg-sky-200 dark:bg-sky-700',
'bg-amber-200 dark:bg-amber-700',
'bg-blue-200 dark:bg-blue-700',
'bg-purple-200 dark:bg-purple-700'
]
export function bgColorForString(input: string): string {
let charCodeSum = 0;
for (let i = 0; i < input.length; i++) {
charCodeSum += input.charCodeAt(i)
}
return randomColors[charCodeSum % randomColors.length];
}
// -----------------------------------------------------------------------------
// Text and strings
// -----------------------------------------------------------------------------
export function clearSelection() {
window.getSelection()?.removeAllRanges();
};
const promise = () => new Promise((resolve) => setTimeout(resolve, 2000))
export function testToast() {
let delay = 150
toast('Toast', {
description: "Description bjksad fkjlhsd fkjhsdf jkshdf jkashdf adskljhf ", action: {
label: 'Undo',
onClick: () => console.log('Undo')
}
})
setTimeout(() => {
toast.info('Info', {
action: {
label: 'Undo',
onClick: () => console.log('Undo')
}
})
}, delay * 1)
setTimeout(() => { toast.success('Success', { description: "description" }) }, delay * 2)
setTimeout(() => { toast.warning('Warning', { description: "description" }) }, delay * 3)
setTimeout(() => { toast.error('Error', { description: "description" }) }, delay * 4)
setTimeout(() => {
toast.promise(promise, {
loading: 'Loading...',
success: (data) => {
return `${data.name} toast has been added`;
},
error: (data: any) => 'Error',
})
}, delay * 5)
}
export function loremIpsum(numWords: number): string {
let text = `Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
@@ -130,15 +215,9 @@ Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming
return text.split(" ").splice(0, numWords).join(" ");
}
export function randomDate(): Date {
let d = new Date()
d.setDate(d.getDate() - Math.random() * 20)
return d
}
// -----------------------------------------------------------------------------
// Hotkeys
// Keyboard shortcuts
// -----------------------------------------------------------------------------
// Füge diese Typdefinitionen am Anfang der Datei hinzu
@@ -209,11 +288,6 @@ export function hotkey(
.map(key => normalizeKeyName(key))
.join('+')
// Überprüfen, ob der Shortcut bereits registriert ist
if (registeredHotkeys.has(normalizedCombination)) {
console.warn(`Hotkey '${keyCombination}' is already registered. Overwriting existing hotkey.`)
}
// Speichern der Hotkey-Informationen
registeredHotkeys.set(normalizedCombination, {
callback,
@@ -319,4 +393,41 @@ window.addEventListener('keydown', handleKeyboardEvent);
// Füge die Funktion zum Entfernen aller Hotkeys hinzu
export function removeAllHotkeys() {
registeredHotkeys.clear()
}
// -----------------------------------------------------------------------------
// Misc
// -----------------------------------------------------------------------------
const promise = () => new Promise((resolve) => setTimeout(resolve, 2000))
export function testToast() {
let delay = 150
toast('Toast', {
description: "Description bjksad fkjlhsd fkjhsdf jkshdf jkashdf adskljhf ", action: {
label: 'Undo',
onClick: () => console.log('Undo')
}
})
setTimeout(() => {
toast.info('Info', {
action: {
label: 'Undo',
onClick: () => console.log('Undo')
}
})
}, delay * 1)
setTimeout(() => { toast.success('Success', { description: "description" }) }, delay * 2)
setTimeout(() => { toast.warning('Warning', { description: "description" }) }, delay * 3)
setTimeout(() => { toast.error('Error', { description: "description" }) }, delay * 4)
setTimeout(() => {
toast.promise(promise, {
loading: 'Loading...',
success: (data) => {
return `${data.name} toast has been added`;
},
error: (data: any) => 'Error',
})
}, delay * 5)
}