Time Changes

This commit is contained in:
2025-12-16 16:23:12 +01:00
parent 780b899d42
commit 6d8193296e
3 changed files with 534 additions and 559 deletions

View File

@@ -5,156 +5,115 @@ export const useStaffTime = () => {
const { $api, $dayjs } = useNuxtApp()
const auth = useAuthStore()
/**
* Lädt die Zeitspannen (Spans) für die Liste.
* Nutzt jetzt GET /api/staff/time/spans
*/
// ... (list Funktion bleibt gleich) ...
const list = async (filter?: { user_id?: string, from?: string, to?: string }) => {
// Standard: Aktueller Monat
// ... (Code wie zuvor)
const from = filter?.from || $dayjs().startOf('month').format('YYYY-MM-DD')
const to = filter?.to || $dayjs().endOf('month').format('YYYY-MM-DD')
// Ziel-User: Entweder aus Filter (Admin-Ansicht) oder eigener User
const targetUserId = filter?.user_id || auth.user.id
const params = new URLSearchParams({
from,
to,
// Der Endpoint erwartet targetUserId, wenn man Daten eines anderen Users will
targetUserId
})
const params = new URLSearchParams({ from, to, targetUserId })
try {
// 💡 UPDATE: Prefix /api hinzugefügt
const spans = await $api(`/api/staff/time/spans?${params.toString()}`)
return (spans || []).map((span: any) => {
const start = $dayjs(span.startedAt)
// Wenn endedAt null ist, läuft die Zeit noch -> Dauer bis "jetzt" berechnen für Anzeige
const end = span.endedAt ? $dayjs(span.endedAt) : $dayjs()
const duration = end.diff(start, 'minute')
return {
// ID: Wir nehmen die erste Event-ID (Start-Event) als Referenz für Aktionen
id: span.sourceEventIds && span.sourceEventIds.length > 0 ? span.sourceEventIds[0] : null,
// Mapping Backend-Status -> Frontend-State
eventIds: span.sourceEventIds || [],
state: span.status,
// Zeitstempel
started_at: span.startedAt,
stopped_at: span.endedAt,
duration_minutes: duration,
// Da der Endpoint nur die Spans zurückgibt, setzen wir die UserID
// auf den User, den wir angefragt haben.
duration_minutes: end.diff(start, 'minute'),
user_id: targetUserId,
type: span.type,
// Payload/Description falls vorhanden
description: span.payload?.description || ''
}
}).sort((a: any, b: any) => $dayjs(b.started_at).valueOf() - $dayjs(a.started_at).valueOf()) // Sortierung: Neueste oben
}).sort((a: any, b: any) => $dayjs(b.started_at).valueOf() - $dayjs(a.started_at).valueOf())
} catch (error) {
console.error("Fehler beim Laden der Zeiten:", error)
console.error("Fehler beim Laden:", error)
return []
}
}
/**
* Startet einen neuen Zeiteintrag.
* POST /api/staff/time/event
* Startet "jetzt" (Live-Modus).
* Kann optional eine Zeit empfangen (für manuelle Korrekturen),
* aber wir nutzen dafür besser die createEntry Funktion unten.
*/
const start = async (description = "Arbeitszeit") => {
try {
// 💡 UPDATE: Prefix /api hinzugefügt
await $api('/api/staff/time/event', {
method: 'POST',
body: {
eventtype: 'work_start',
eventtime: new Date().toISOString(),
payload: { description }
}
})
} catch (error) {
console.error("Fehler beim Starten:", error)
throw error
}
const start = async (description = "Arbeitszeit", time?: string) => {
await $api('/api/staff/time/event', {
method: 'POST',
body: {
eventtype: 'work_start',
eventtime: time || new Date().toISOString(), // 💡 Fix: Zeit akzeptieren
payload: { description }
}
})
}
/**
* Stoppt die aktuelle Zeit.
* POST /api/staff/time/event
*/
const stop = async (entryId?: string) => {
try {
// 💡 UPDATE: Prefix /api hinzugefügt
await $api('/api/staff/time/event', {
method: 'POST',
body: {
eventtype: 'work_end',
eventtime: new Date().toISOString()
}
})
} catch (error) {
console.error("Fehler beim Stoppen:", error)
throw error
}
const stop = async () => {
await $api('/api/staff/time/event', { method: 'POST', body: { eventtype: 'work_end', eventtime: new Date().toISOString() } })
}
/**
* Reicht einen Eintrag ein.
* POST /api/staff/time/submit
*/
const submit = async (entryId: string) => {
if (!entryId) return
try {
// 💡 UPDATE: Prefix /api hinzugefügt
await $api('/api/staff/time/submit', {
method: 'POST',
body: {
eventIds: [entryId]
}
})
} catch (error) {
console.error("Fehler beim Einreichen:", error)
throw error
}
const submit = async (entry: any) => {
const ids = entry.eventIds || (entry.id ? [entry.id] : [entry]);
if (!ids || ids.length === 0) return
await $api('/api/staff/time/submit', { method: 'POST', body: { eventIds: ids } })
}
/**
* Genehmigt einen Eintrag.
* POST /api/staff/time/approve
*/
const approve = async (entry: any) => {
if (!entry || !entry.id || !entry.user_id) {
console.error("Ungültiger Eintrag für Genehmigung (ID oder UserID fehlt)", entry)
return
}
if (!entry?.user_id) return
const ids = entry.eventIds || [entry.id];
await $api('/api/staff/time/approve', { method: 'POST', body: { eventIds: ids, employeeUserId: entry.user_id } })
}
try {
// 💡 UPDATE: Prefix /api hinzugefügt
await $api('/api/staff/time/approve', {
const reject = async (entry: any, reason = "Abgelehnt") => {
if (!entry?.user_id) return
const ids = entry.eventIds || [entry.id];
await $api('/api/staff/time/reject', { method: 'POST', body: { eventIds: ids, employeeUserId: entry.user_id, reason } })
}
const update = async (entry: any, newData: { start: string, end: string | null, type: string, description: string }) => {
if (!entry || !entry.eventIds || entry.eventIds.length === 0) {
throw new Error("Bearbeiten fehlgeschlagen: Keine IDs.")
}
await $api('/api/staff/time/edit', {
method: 'POST',
body: {
originalEventIds: entry.eventIds,
newStart: newData.start,
newEnd: newData.end,
newType: newData.type,
description: newData.description,
reason: "Manuelle Bearbeitung"
}
})
}
// 🆕 NEU: Manuellen Eintrag erstellen (Vergangenheit oder Zeitraum)
const createEntry = async (data: { start: string, end: string | null, type: string, description: string }) => {
// 1. Start Event senden
// Wir nutzen den dynamischen Typ (work_start, vacation_start etc.)
await $api('/api/staff/time/event', {
method: 'POST',
body: {
eventtype: `${data.type}_start`,
eventtime: data.start,
payload: { description: data.description }
}
})
// 2. End Event senden (falls vorhanden)
if (data.end) {
await $api('/api/staff/time/event', {
method: 'POST',
body: {
eventIds: [entry.id],
employeeUserId: entry.user_id
eventtype: `${data.type}_end`,
eventtime: data.end
}
})
} catch (error) {
console.error("Fehler beim Genehmigen:", error)
throw error
}
}
return {
list,
start,
stop,
submit,
approve
}
return { list, start, stop, submit, approve, reject, update, createEntry }
}