Vue 3 + FastAPI Webapp zur Anzeige von Filebot/n8n-Medienmetadaten aus PostgreSQL. Enthält Frontend, API, Nginx-Config, SQL-Migrationen und Docker-Compose-Setup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
105 lines
2.7 KiB
TypeScript
105 lines
2.7 KiB
TypeScript
export interface DateTimeBound {
|
|
date: string
|
|
hour: string
|
|
minute: string
|
|
}
|
|
|
|
export const emptyDateTimeBound = (): DateTimeBound => ({
|
|
date: '',
|
|
hour: '00',
|
|
minute: '00',
|
|
})
|
|
|
|
export function boundToIso(bound: DateTimeBound): string | undefined {
|
|
if (!bound.date) return undefined
|
|
const local = new Date(
|
|
`${bound.date}T${bound.hour.padStart(2, '0')}:${bound.minute.padStart(2, '0')}:00`
|
|
)
|
|
if (Number.isNaN(local.getTime())) return undefined
|
|
return local.toISOString()
|
|
}
|
|
|
|
export function formatBoundLabel(bound: DateTimeBound): string {
|
|
if (!bound.date) return 'Datum wählen'
|
|
return `${formatDateDe(bound.date)} ${bound.hour.padStart(2, '0')}:${bound.minute.padStart(2, '0')}`
|
|
}
|
|
|
|
export function formatDateDe(isoDate: string): string {
|
|
const [y, m, d] = isoDate.split('-').map(Number)
|
|
if (!y || !m || !d) return isoDate
|
|
return new Date(y, m - 1, d).toLocaleDateString('de-DE', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric',
|
|
})
|
|
}
|
|
|
|
export function pad2(n: number): string {
|
|
return String(n).padStart(2, '0')
|
|
}
|
|
|
|
export const HOURS = Array.from({ length: 24 }, (_, i) => pad2(i))
|
|
export const MINUTES = Array.from({ length: 60 }, (_, i) => pad2(i))
|
|
|
|
const WEEKDAYS = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
|
|
const MONTHS = [
|
|
'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
|
|
'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember',
|
|
]
|
|
|
|
export function getWeekdayLabels(): string[] {
|
|
return WEEKDAYS
|
|
}
|
|
|
|
export function getMonthLabel(monthIndex: number): string {
|
|
return MONTHS[monthIndex] ?? ''
|
|
}
|
|
|
|
/** Kalendertage inkl. Auffüllung für Mo-start Grid */
|
|
export function getCalendarDays(year: number, month: number) {
|
|
const first = new Date(year, month, 1)
|
|
const last = new Date(year, month + 1, 0)
|
|
let startPad = first.getDay() - 1
|
|
if (startPad < 0) startPad = 6
|
|
|
|
const days: { date: string; day: number; currentMonth: boolean }[] = []
|
|
|
|
for (let i = startPad - 1; i >= 0; i--) {
|
|
const d = new Date(year, month, -i)
|
|
days.push({
|
|
date: toIsoDate(d),
|
|
day: d.getDate(),
|
|
currentMonth: false,
|
|
})
|
|
}
|
|
|
|
for (let d = 1; d <= last.getDate(); d++) {
|
|
days.push({
|
|
date: toIsoDate(new Date(year, month, d)),
|
|
day: d,
|
|
currentMonth: true,
|
|
})
|
|
}
|
|
|
|
const totalCells = Math.ceil((startPad + last.getDate()) / 7) * 7
|
|
let nextDay = 1
|
|
while (days.length < totalCells) {
|
|
const d = new Date(year, month + 1, nextDay++)
|
|
days.push({
|
|
date: toIsoDate(d),
|
|
day: d.getDate(),
|
|
currentMonth: false,
|
|
})
|
|
}
|
|
|
|
return days
|
|
}
|
|
|
|
export function toIsoDate(d: Date): string {
|
|
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`
|
|
}
|
|
|
|
export function isBoundActive(bound: DateTimeBound): boolean {
|
|
return Boolean(bound.date)
|
|
}
|