feat(kalender): Kalender mit Urlauben und Feiertagen fuer alle
Neuer Menuepunkt "Kalender" fuer alle Rollen: genehmigte Urlaube aller Mitarbeiter, auch in der Zukunft, dazu Feiertage. Monatsansicht (Standard) und Zeitleiste, filterbar nach Team und Name. - Eigene Tabelle pulse_calendar_days, gefuellt von lib/calendarSync.js im HRworks-Lauf (Fenster bis 400 Tage voraus). Buchungen entstehen weiter erst am jeweiligen Tag. - Nur validatedOk und nur freigegebene Arten (calendar_types, Haken in den HRworks-Einstellungen). Krankmeldungen werden dafuer nicht abgefragt. - GET /api/calendar fuer alle Angemeldeten, ohne Mails und Profilbilder. - Timer laeuft zusaetzlich um 12:00 Uhr. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6ae5a01bda
commit
c0eb00faee
@@ -9,7 +9,8 @@ import { useToast } from '../Toast';
|
||||
* Abwesenheiten aus HRworks.
|
||||
*
|
||||
* Urlaub, Krankheit, Elternzeit und Feiertage stehen in HRworks; Pulse holt sie
|
||||
* einmal taeglich und bucht sie auf ein nicht abrechenbares Projekt. Hier
|
||||
* zweimal taeglich, bucht sie auf ein nicht abrechenbares Projekt und fuellt
|
||||
* den Kalender (nur Urlaub und Feiertage). Hier
|
||||
* stehen die Zugangsdaten, die Zuordnung der Arten auf Tasks und der Knopf fuer
|
||||
* einen Probelauf.
|
||||
*/
|
||||
@@ -44,10 +45,12 @@ export const HrworksSettings: React.FC<{ settings: AdminSettings; onSaved: () =>
|
||||
setReport(r);
|
||||
addToast(
|
||||
was === 'apply'
|
||||
? `Übernommen: ${r.created} neu, ${r.updated ?? 0} geändert, ${r.removed ?? 0} entfernt.`
|
||||
? `Übernommen: ${r.created} neu, ${r.updated ?? 0} geändert, ${r.removed ?? 0} entfernt.` +
|
||||
(r.calendar ? ` Kalender: ${r.calendar.vacation_days} Urlaubstage.` : '')
|
||||
: `Probelauf: ${r.planned_create} neu, ${r.planned_update} geändert, ${r.planned_delete} zu entfernen.`,
|
||||
'success'
|
||||
);
|
||||
if (r.calendar_error) addToast(`Kalender: ${r.calendar_error}`, 'error');
|
||||
hrworksApi.status().then(setStatus).catch(() => undefined);
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -82,7 +85,7 @@ export const HrworksSettings: React.FC<{ settings: AdminSettings; onSaved: () =>
|
||||
<Icon name={settings.hrworks.enabled ? 'check' : 'info'} className="mt-0.5 h-5 w-5 shrink-0" />
|
||||
<span>
|
||||
{settings.hrworks.enabled
|
||||
? 'Der Abgleich läuft täglich um 5:30 Uhr und holt die letzten Tage nach.'
|
||||
? 'Der Abgleich läuft täglich um 5:30 und 12:00 Uhr: Buchungen bis heute, dazu der Kalender mit den genehmigten Urlauben der Zukunft.'
|
||||
: settings.hrworks.configured
|
||||
? 'Zugangsdaten hinterlegt, der Abgleich ist noch nicht eingeschaltet.'
|
||||
: 'Noch keine Zugangsdaten. Schlüsselpaar in HRworks unter Grundlagen → Integrationen → HRworks-API erzeugen.'}
|
||||
@@ -148,7 +151,8 @@ export const HrworksSettings: React.FC<{ settings: AdminSettings; onSaved: () =>
|
||||
<p className="mb-3 text-xs leading-snug text-ink-400">
|
||||
Links der Schlüssel aus HRworks (<code className="rounded bg-ink-100 px-1">absence:</code> oder{' '}
|
||||
<code className="rounded bg-ink-100 px-1">sick:</code>), rechts der Taskname in Pulse. Fehlt ein Eintrag, sucht Pulse
|
||||
einen Task mit dem HRworks-Namen der Art – findet es keinen, meldet der Probelauf ihn als fehlend.
|
||||
einen Task mit dem HRworks-Namen der Art – findet es keinen, meldet der Probelauf ihn als fehlend. Der Haken{' '}
|
||||
<b>Kalender</b> legt fest, welche Arten im Kalender stehen, den alle Mitarbeiter sehen – Krankmeldungen nie.
|
||||
</p>
|
||||
<div className="grid gap-2 sm:grid-cols-2">
|
||||
{eintraege.map(([key, value]) => (
|
||||
@@ -159,6 +163,25 @@ export const HrworksSettings: React.FC<{ settings: AdminSettings; onSaved: () =>
|
||||
value={value}
|
||||
onChange={(e) => set({ type_map: { ...form.type_map, [key]: e.target.value } })}
|
||||
/>
|
||||
{key.startsWith('absence:') ? (
|
||||
<label className="flex shrink-0 cursor-pointer items-center gap-1.5 text-[11px] font-bold text-ink-500" title="Im Kalender für alle zeigen">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="accent-[var(--color-brand-500)]"
|
||||
checked={(form.calendar_types ?? []).includes(key)}
|
||||
onChange={(e) =>
|
||||
set({
|
||||
calendar_types: e.target.checked
|
||||
? [...(form.calendar_types ?? []), key]
|
||||
: (form.calendar_types ?? []).filter((t) => t !== key),
|
||||
})
|
||||
}
|
||||
/>
|
||||
Kalender
|
||||
</label>
|
||||
) : (
|
||||
<span className="w-[66px] shrink-0" />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -193,6 +216,12 @@ export const HrworksSettings: React.FC<{ settings: AdminSettings; onSaved: () =>
|
||||
: ''}
|
||||
</p>
|
||||
)}
|
||||
{status?.calendar?.last_run && (
|
||||
<p className="mt-1 text-xs text-ink-400">
|
||||
Kalender: {new Date(status.calendar.last_run).toLocaleString('de-DE')} – {status.calendar.vacation_days} Urlaubstage,{' '}
|
||||
{status.calendar.holidays} Feiertage.
|
||||
</p>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user