fix(dashboard): restore event visibility and fix lint errors in App.tsx
Appointments: no longer hide existing events on holiday dates Resources: load all overlapping events per group, include inactive/past events, and reload on date/view navigation App.tsx: replace any types in password input handlers with typed event shapes
This commit is contained in:
@@ -439,7 +439,7 @@ const Layout: React.FC = () => {
|
|||||||
type="password"
|
type="password"
|
||||||
placeholder="Aktuelles Passwort"
|
placeholder="Aktuelles Passwort"
|
||||||
value={pwdCurrent}
|
value={pwdCurrent}
|
||||||
input={(e: any) => setPwdCurrent(e.value)}
|
input={(e: { value?: string }) => setPwdCurrent(e.value ?? '')}
|
||||||
disabled={pwdBusy}
|
disabled={pwdBusy}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -449,7 +449,7 @@ const Layout: React.FC = () => {
|
|||||||
type="password"
|
type="password"
|
||||||
placeholder="Mindestens 6 Zeichen"
|
placeholder="Mindestens 6 Zeichen"
|
||||||
value={pwdNew}
|
value={pwdNew}
|
||||||
input={(e: any) => setPwdNew(e.value)}
|
input={(e: { value?: string }) => setPwdNew(e.value ?? '')}
|
||||||
disabled={pwdBusy}
|
disabled={pwdBusy}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -459,7 +459,7 @@ const Layout: React.FC = () => {
|
|||||||
type="password"
|
type="password"
|
||||||
placeholder="Wiederholen"
|
placeholder="Wiederholen"
|
||||||
value={pwdConfirm}
|
value={pwdConfirm}
|
||||||
input={(e: any) => setPwdConfirm(e.value)}
|
input={(e: { value?: string }) => setPwdConfirm(e.value ?? '')}
|
||||||
disabled={pwdBusy}
|
disabled={pwdBusy}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -523,28 +523,10 @@ const Appointments: React.FC = () => {
|
|||||||
}, [holidays, allowScheduleOnHolidays]);
|
}, [holidays, allowScheduleOnHolidays]);
|
||||||
|
|
||||||
const dataSource = useMemo(() => {
|
const dataSource = useMemo(() => {
|
||||||
// Filter: Events with SkipHolidays=true (from internal Event type) are never shown on holidays
|
// Existing events should always be visible; holiday skipping for recurring events
|
||||||
const filteredEvents = events.filter(ev => {
|
// is handled via RecurrenceException from the backend.
|
||||||
if (ev.SkipHolidays) {
|
return [...events, ...holidayDisplayEvents, ...holidayBlockEvents];
|
||||||
// If event falls within a holiday, hide it
|
}, [events, holidayDisplayEvents, holidayBlockEvents]);
|
||||||
const s = ev.StartTime instanceof Date ? ev.StartTime : new Date(ev.StartTime);
|
|
||||||
const e = ev.EndTime instanceof Date ? ev.EndTime : new Date(ev.EndTime);
|
|
||||||
for (const h of holidays) {
|
|
||||||
const hs = new Date(h.start_date + 'T00:00:00');
|
|
||||||
const he = new Date(h.end_date + 'T23:59:59');
|
|
||||||
if (
|
|
||||||
(s >= hs && s <= he) ||
|
|
||||||
(e >= hs && e <= he) ||
|
|
||||||
(s <= hs && e >= he)
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
return [...filteredEvents, ...holidayDisplayEvents, ...holidayBlockEvents];
|
|
||||||
}, [events, holidayDisplayEvents, holidayBlockEvents, holidays]);
|
|
||||||
|
|
||||||
// Removed dataSource logging
|
// Removed dataSource logging
|
||||||
|
|
||||||
@@ -1227,37 +1209,6 @@ const Appointments: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
eventRendered={(args: EventRenderedArgs) => {
|
eventRendered={(args: EventRenderedArgs) => {
|
||||||
// Always hide events that skip holidays when they fall on holidays, regardless of toggle
|
|
||||||
if (args.data) {
|
|
||||||
const ev = args.data as unknown as Partial<Event>;
|
|
||||||
if (ev.SkipHolidays && !args.data.isHoliday) {
|
|
||||||
const s =
|
|
||||||
args.data.StartTime instanceof Date
|
|
||||||
? args.data.StartTime
|
|
||||||
: new Date(args.data.StartTime);
|
|
||||||
const e =
|
|
||||||
args.data.EndTime instanceof Date ? args.data.EndTime : new Date(args.data.EndTime);
|
|
||||||
if (isWithinHolidayRange(s, e)) {
|
|
||||||
args.cancel = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blende Nicht-Ferien-Events aus, falls sie in Ferien fallen und Terminieren nicht erlaubt ist
|
|
||||||
// Hide events on holidays if not allowed
|
|
||||||
if (!allowScheduleOnHolidays && args.data && !args.data.isHoliday) {
|
|
||||||
const s =
|
|
||||||
args.data.StartTime instanceof Date
|
|
||||||
? args.data.StartTime
|
|
||||||
: new Date(args.data.StartTime);
|
|
||||||
const e =
|
|
||||||
args.data.EndTime instanceof Date ? args.data.EndTime : new Date(args.data.EndTime);
|
|
||||||
if (isWithinHolidayRange(s, e)) {
|
|
||||||
args.cancel = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedGroupId && args.data && args.data.Id) {
|
if (selectedGroupId && args.data && args.data.Id) {
|
||||||
const groupColor = getGroupColor(selectedGroupId, groups);
|
const groupColor = getGroupColor(selectedGroupId, groups);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const Ressourcen: React.FC = () => {
|
|||||||
const [groupOrder, setGroupOrder] = useState<number[]>([]);
|
const [groupOrder, setGroupOrder] = useState<number[]>([]);
|
||||||
const [showOrderPanel, setShowOrderPanel] = useState<boolean>(false);
|
const [showOrderPanel, setShowOrderPanel] = useState<boolean>(false);
|
||||||
const [timelineView] = useState<TimelineView>('day');
|
const [timelineView] = useState<TimelineView>('day');
|
||||||
const [viewDate] = useState<Date>(() => {
|
const [viewDate, setViewDate] = useState<Date>(() => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
now.setHours(0, 0, 0, 0);
|
now.setHours(0, 0, 0, 0);
|
||||||
return now;
|
return now;
|
||||||
@@ -110,23 +110,31 @@ const Ressourcen: React.FC = () => {
|
|||||||
for (const group of groups) {
|
for (const group of groups) {
|
||||||
try {
|
try {
|
||||||
console.log(`[Ressourcen] Fetching events for group "${group.name}" (ID: ${group.id})`);
|
console.log(`[Ressourcen] Fetching events for group "${group.name}" (ID: ${group.id})`);
|
||||||
const apiEvents = await fetchEvents(group.id.toString(), false, {
|
const apiEvents = await fetchEvents(group.id.toString(), true, {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
});
|
});
|
||||||
console.log(`[Ressourcen] Got ${apiEvents?.length || 0} events for group "${group.name}"`);
|
console.log(`[Ressourcen] Got ${apiEvents?.length || 0} events for group "${group.name}"`);
|
||||||
|
|
||||||
if (Array.isArray(apiEvents) && apiEvents.length > 0) {
|
if (Array.isArray(apiEvents) && apiEvents.length > 0) {
|
||||||
const event = apiEvents[0];
|
for (const event of apiEvents) {
|
||||||
const eventTitle = event.subject || event.title || 'Unnamed Event';
|
const eventTitle = event.subject || event.title || 'Unnamed Event';
|
||||||
const eventType = event.type || event.event_type || 'other';
|
const eventType = event.type || event.event_type || 'other';
|
||||||
const eventStart = event.startTime || event.start;
|
const eventStart = event.startTime || event.start;
|
||||||
const eventEnd = event.endTime || event.end;
|
const eventEnd = event.endTime || event.end;
|
||||||
|
|
||||||
if (eventStart && eventEnd) {
|
if (!eventStart || !eventEnd) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const parsedStart = parseUTCDate(eventStart);
|
const parsedStart = parseUTCDate(eventStart);
|
||||||
const parsedEnd = parseUTCDate(eventEnd);
|
const parsedEnd = parseUTCDate(eventEnd);
|
||||||
|
|
||||||
|
// Keep only events that overlap the visible range.
|
||||||
|
if (parsedEnd < start || parsedStart > end) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Capitalize first letter of event type
|
// Capitalize first letter of event type
|
||||||
const formattedType = eventType.charAt(0).toUpperCase() + eventType.slice(1);
|
const formattedType = eventType.charAt(0).toUpperCase() + eventType.slice(1);
|
||||||
|
|
||||||
@@ -138,7 +146,6 @@ const Ressourcen: React.FC = () => {
|
|||||||
ResourceId: group.id,
|
ResourceId: group.id,
|
||||||
EventType: eventType,
|
EventType: eventType,
|
||||||
});
|
});
|
||||||
console.log(`[Ressourcen] Group "${group.name}" has event: ${eventTitle}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -324,6 +331,16 @@ const Ressourcen: React.FC = () => {
|
|||||||
group={{ resources: ['Groups'], allowGroupEdit: false }}
|
group={{ resources: ['Groups'], allowGroupEdit: false }}
|
||||||
timeScale={{ interval: 60, slotCount: 1 }}
|
timeScale={{ interval: 60, slotCount: 1 }}
|
||||||
rowAutoHeight={false}
|
rowAutoHeight={false}
|
||||||
|
actionComplete={(args) => {
|
||||||
|
if (args.requestType === 'dateNavigate' || args.requestType === 'viewNavigate') {
|
||||||
|
const selected = scheduleRef.current?.selectedDate;
|
||||||
|
if (selected) {
|
||||||
|
const normalized = new Date(selected);
|
||||||
|
normalized.setHours(0, 0, 0, 0);
|
||||||
|
setViewDate(normalized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ViewsDirective>
|
<ViewsDirective>
|
||||||
<ViewDirective option="TimelineDay" displayName="Tag"></ViewDirective>
|
<ViewDirective option="TimelineDay" displayName="Tag"></ViewDirective>
|
||||||
|
|||||||
Reference in New Issue
Block a user