ein runtime error

This commit is contained in:
2025-10-16 00:17:30 +02:00
parent d60a6d9fae
commit 7b2256c0ed
10 changed files with 119 additions and 68 deletions

View File

@@ -4,8 +4,9 @@ import { Link } from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { shiftPlanService } from '../../services/shiftPlanService';
import { employeeService } from '../../services/employeeService';
import { ShiftPlan } from '../../models/ShiftPlan';
import { ShiftPlan, ScheduledShift } from '../../models/ShiftPlan';
import { Employee } from '../../models/Employee';
import { shiftAssignmentService } from '../../services/shiftAssignmentService';
interface DashboardData {
currentShiftPlan: ShiftPlan | null;
@@ -29,6 +30,7 @@ interface DashboardData {
const Dashboard: React.FC = () => {
const { user, hasRole } = useAuth();
const [loading, setLoading] = useState(true);
const [currentPlanShifts, setCurrentPlanShifts] = useState<ScheduledShift[]>([]);
const [data, setData] = useState<DashboardData>({
currentShiftPlan: null,
upcomingShifts: [],
@@ -53,13 +55,25 @@ const Dashboard: React.FC = () => {
const [shiftPlans, employees] = await Promise.all([
shiftPlanService.getShiftPlans(),
employeeService.getEmployees()
employeeService.getEmployees(),
]);
// Find current shift plan
const today = new Date().toISOString().split('T')[0];
const currentPlan = findCurrentShiftPlan(shiftPlans, today);
// Load shifts for current plan
if (currentPlan) {
const shifts = await shiftAssignmentService.getScheduledShiftsForPlan(currentPlan.id);
setCurrentPlanShifts(shifts);
} else {
setCurrentPlanShifts([]);
}
console.log('📊 Loaded data:', {
plans: shiftPlans.length,
employees: employees.length,
plansWithShifts: shiftPlans.filter(p => p.scheduledShifts && p.scheduledShifts.length > 0).length
currentPlanShifts
});
// Debug: Log plan details
@@ -68,14 +82,14 @@ const Dashboard: React.FC = () => {
status: plan.status,
startDate: plan.startDate,
endDate: plan.endDate,
scheduledShifts: plan.scheduledShifts?.length || 0,
//scheduledShifts: plan.scheduledShifts?.length || 0,
isTemplate: plan.isTemplate
});
});
// Find current shift plan (published and current date within range)
const today = new Date().toISOString().split('T')[0];
const currentPlan = findCurrentShiftPlan(shiftPlans, today);
//const today = new Date().toISOString().split('T')[0];
//const currentPlan = findCurrentShiftPlan(shiftPlans, today);
// Get user's upcoming shifts
const userShifts = await loadUserUpcomingShifts(shiftPlans, today);
@@ -96,7 +110,7 @@ const Dashboard: React.FC = () => {
console.log('✅ Dashboard data loaded:', {
currentPlan: currentPlan?.name,
userShifts: userShifts.length,
//userShifts: userShifts.length,
teamStats,
recentPlans: recentPlans.length
});
@@ -142,13 +156,14 @@ const Dashboard: React.FC = () => {
// Check each plan for user assignments
for (const plan of shiftPlans) {
if (plan.status !== 'published' || !plan.scheduledShifts || plan.scheduledShifts.length === 0) {
const scheduledShifts = (await shiftAssignmentService.getScheduledShiftsForPlan(plan.id));
if (plan.status !== 'published' || scheduledShifts.length === 0) {
continue;
}
console.log(`🔍 Checking plan ${plan.name} for user shifts:`, plan.scheduledShifts.length);
console.log(`🔍 Checking plan ${plan.name} for user shifts:`, scheduledShifts.length);
for (const scheduledShift of plan.scheduledShifts) {
for (const scheduledShift of scheduledShifts) {
// Ensure assignedEmployees is an array
const assignedEmployees = Array.isArray(scheduledShift.assignedEmployees)
? scheduledShift.assignedEmployees
@@ -237,16 +252,19 @@ const Dashboard: React.FC = () => {
return `${start} - ${end}`;
};
const calculatePlanProgress = (plan: ShiftPlan): { covered: number; total: number; percentage: number } => {
if (!plan.scheduledShifts || plan.scheduledShifts.length === 0) {
const calculatePlanProgress = (plan: ShiftPlan, shifts: ScheduledShift[]): {
covered: number; total: number; percentage: number
} => {
if (!plan.id || shifts.length === 0) {
console.log(`📊 Plan ${plan.name} has no scheduled shifts`);
return { covered: 0, total: 0, percentage: 0 };
}
const totalShifts = plan.scheduledShifts.length;
const coveredShifts = plan.scheduledShifts.filter(shift => {
const assigned = Array.isArray(shift.assignedEmployees) ? shift.assignedEmployees : [];
return assigned.length > 0;
const currentDate = new Date();
const totalShifts = shifts.length;
const coveredShifts = shifts.filter(shift => {
const shiftDate = new Date(shift.date);
return currentDate > shiftDate;
}).length;
const percentage = totalShifts > 0 ? Math.round((coveredShifts / totalShifts) * 100) : 0;
@@ -302,7 +320,7 @@ const Dashboard: React.FC = () => {
<div><strong>End Date:</strong> {data.currentShiftPlan.endDate}</div>
<div><strong>Shifts Defined:</strong> {data.currentShiftPlan.shifts?.length || 0}</div>
<div><strong>Time Slots:</strong> {data.currentShiftPlan.timeSlots?.length || 0}</div>
<div><strong>Scheduled Shifts:</strong> {data.currentShiftPlan.scheduledShifts?.length || 0}</div>
<div><strong>Scheduled Shifts:</strong> {data.currentShiftPlan.shifts.length || 0}</div>
{data.currentShiftPlan.shifts && data.currentShiftPlan.shifts.length > 0 && (
<div style={{ marginTop: '10px' }}>
@@ -319,7 +337,9 @@ const Dashboard: React.FC = () => {
);
};
const progress = data.currentShiftPlan ? calculatePlanProgress(data.currentShiftPlan) : { covered: 0, total: 0, percentage: 0 };
const progress = data.currentShiftPlan
? calculatePlanProgress(data.currentShiftPlan, currentPlanShifts)
: { covered: 0, total: 0, percentage: 0 };
return (
<div>

View File

@@ -10,6 +10,7 @@ import { ShiftPlan, TimeSlot } from '../../models/ShiftPlan';
import { Employee, EmployeeAvailability } from '../../models/Employee';
import { useNotification } from '../../contexts/NotificationContext';
import { formatDate, formatTime } from '../../utils/foramatters';
import { isScheduledShift } from '../../models/helpers';
// Local interface extensions (same as AvailabilityManager)
interface ExtendedTimeSlot extends TimeSlot {
@@ -148,7 +149,7 @@ const ShiftPlanView: React.FC = () => {
return date.getDay() === 0 ? 7 : date.getDay();
};
const debugManagerAvailability = () => {
/*const debugManagerAvailability = () => {
if (!shiftPlan || !employees.length || !availabilities.length) return;
const manager = employees.find(emp => emp.role === 'admin');
@@ -196,7 +197,7 @@ const ShiftPlanView: React.FC = () => {
});
}
});
};
};*/
const handlePreviewAssignment = async () => {
if (!shiftPlan) return;
@@ -282,13 +283,15 @@ const ShiftPlanView: React.FC = () => {
console.log('🔄 Starting to publish assignments...');
const scheduledShifts = await shiftAssignmentService.getScheduledShiftsForPlan(shiftPlan.id);
// Debug: Check if scheduled shifts exist
if (!shiftPlan.scheduledShifts || shiftPlan.scheduledShifts.length === 0) {
if (!scheduledShifts || scheduledShifts.length === 0) {
throw new Error('No scheduled shifts found in the plan');
}
// Update scheduled shifts with assignments
const updatePromises = shiftPlan.scheduledShifts.map(async (scheduledShift) => {
const updatePromises = scheduledShifts.map(async (scheduledShift) => {
const assignedEmployees = assignmentResult.assignments[scheduledShift.id] || [];
console.log(`📝 Updating shift ${scheduledShift.id} with`, assignedEmployees.length, 'employees');
@@ -375,10 +378,11 @@ const ShiftPlanView: React.FC = () => {
message: 'Schichtplan wurde erfolgreich zurück in den Entwurfsstatus gesetzt. Alle Daten wurden neu geladen.'
});
const scheduledShifts = await shiftAssignmentService.getScheduledShiftsForPlan(shiftPlan.id);
console.log('Scheduled shifts after revert:', {
hasScheduledShifts: !!shiftPlan.scheduledShifts,
count: shiftPlan.scheduledShifts?.length || 0,
firstFew: shiftPlan.scheduledShifts?.slice(0, 3)
hasScheduledShifts: !! scheduledShifts,
count: scheduledShifts.length || 0,
firstFew: scheduledShifts?.slice(0, 3)
});
} catch (error) {
@@ -419,8 +423,15 @@ const ShiftPlanView: React.FC = () => {
};
// Render timetable using the same structure as AvailabilityManager
const renderTimetable = () => {
const renderTimetable = async () => {
const { days, allTimeSlots, timeSlotsByDay } = getTimetableData();
if (!shiftPlan?.id) {
console.warn("Shift plan ID is missing");
return []; // safely exit
}
const scheduledShifts = await shiftAssignmentService.getScheduledShiftsForPlan(shiftPlan.id);
if (days.length === 0 || allTimeSlots.length === 0) {
return (
@@ -524,9 +535,11 @@ const ShiftPlanView: React.FC = () => {
let assignedEmployees: string[] = [];
let displayText = '';
if (shiftPlan?.status === 'published' && shiftPlan.scheduledShifts) {
if (shiftPlan?.status === 'published' && scheduledShifts) {
// For published plans, use actual assignments from scheduled shifts
const scheduledShift = shiftPlan.scheduledShifts.find(scheduled => {
const scheduledShift = scheduledShifts.find(scheduled => {
const scheduledDayOfWeek = getDayOfWeek(scheduled.date);
return scheduledDayOfWeek === weekday.id &&
scheduled.timeSlotId === timeSlot.id;
@@ -541,7 +554,7 @@ const ShiftPlanView: React.FC = () => {
}
} else if (assignmentResult) {
// For draft with preview, use assignment result
const scheduledShift = shiftPlan?.scheduledShifts?.find(scheduled => {
const scheduledShift = scheduledShifts?.find(scheduled => {
const scheduledDayOfWeek = getDayOfWeek(scheduled.date);
return scheduledDayOfWeek === weekday.id &&
scheduled.timeSlotId === timeSlot.id;
@@ -594,8 +607,9 @@ const ShiftPlanView: React.FC = () => {
if (loading) return <div>Lade Schichtplan...</div>;
if (!shiftPlan) return <div>Schichtplan nicht gefunden</div>;
const availabilityStatus = getAvailabilityStatus();
const { days, allTimeSlots } = getTimetableData();
const availabilityStatus = getAvailabilityStatus();
return (
<div style={{ padding: '20px' }}>