mirror of
https://github.com/donpat1to/Schichtenplaner.git
synced 2025-12-01 06:55:45 +01:00
removed users table relicts
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { shiftPlanService } from '../../services/shiftPlanService';
|
||||
import { ShiftPlan, Shift } from '../../../../backend/src/models/shiftPlan';
|
||||
import { ShiftPlan, Shift, ScheduledShift } from '../../models/ShiftPlan';
|
||||
import { useNotification } from '../../contexts/NotificationContext';
|
||||
import { getTimeSlotById } from '../../models/helpers/shiftPlanHelpers';
|
||||
|
||||
const ShiftPlanEdit: React.FC = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
@@ -13,9 +12,9 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
const [shiftPlan, setShiftPlan] = useState<ShiftPlan | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [editingShift, setEditingShift] = useState<Shift | null>(null);
|
||||
const [newShift, setNewShift] = useState<Partial<ScheduledShift>>({
|
||||
date: '',
|
||||
const [newShift, setNewShift] = useState<Partial<Shift>>({
|
||||
timeSlotId: '',
|
||||
dayOfWeek: 1,
|
||||
requiredEmployees: 1
|
||||
});
|
||||
|
||||
@@ -45,6 +44,7 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
if (!shiftPlan || !id) return;
|
||||
|
||||
try {
|
||||
// Update logic here
|
||||
loadShiftPlan();
|
||||
setEditingShift(null);
|
||||
} catch (error) {
|
||||
@@ -60,26 +60,25 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
const handleAddShift = async () => {
|
||||
if (!shiftPlan || !id) return;
|
||||
|
||||
if (!getTimeSlotById(shiftPlan, newShift.timeSlotId?) || !newShift.name || !newShift.startTime || !newShift.endTime || !newShift.requiredEmployees) {
|
||||
if (!newShift.timeSlotId || !newShift.requiredEmployees) {
|
||||
showNotification({
|
||||
type: 'error',
|
||||
title: 'Fehler',
|
||||
message: 'Bitte füllen Sie alle Pflichtfelder aus.'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Add shift logic here
|
||||
showNotification({
|
||||
type: 'success',
|
||||
title: 'Erfolg',
|
||||
message: 'Neue Schicht wurde hinzugefügt.'
|
||||
});
|
||||
setNewShift({
|
||||
date: '',
|
||||
name: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
timeSlotId: '',
|
||||
dayOfWeek: 1,
|
||||
requiredEmployees: 1
|
||||
});
|
||||
loadShiftPlan();
|
||||
@@ -99,6 +98,7 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
// Delete logic here
|
||||
loadShiftPlan();
|
||||
} catch (error) {
|
||||
console.error('Error deleting shift:', error);
|
||||
@@ -142,14 +142,24 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
return <div>Schichtplan nicht gefunden</div>;
|
||||
}
|
||||
|
||||
// Group shifts by date
|
||||
const shiftsByDate = shiftPlan.shifts.reduce((acc, shift) => {
|
||||
if (!acc[shift.date]) {
|
||||
acc[shift.date] = [];
|
||||
// Group shifts by dayOfWeek
|
||||
const shiftsByDay = shiftPlan.shifts.reduce((acc, shift) => {
|
||||
if (!acc[shift.dayOfWeek]) {
|
||||
acc[shift.dayOfWeek] = [];
|
||||
}
|
||||
acc[shift.date].push(shift);
|
||||
acc[shift.dayOfWeek].push(shift);
|
||||
return acc;
|
||||
}, {} as Record<string, typeof shiftPlan.shifts>);
|
||||
}, {} as Record<number, typeof shiftPlan.shifts>);
|
||||
|
||||
const daysOfWeek = [
|
||||
{ id: 1, name: 'Montag' },
|
||||
{ id: 2, name: 'Dienstag' },
|
||||
{ id: 3, name: 'Mittwoch' },
|
||||
{ id: 4, name: 'Donnerstag' },
|
||||
{ id: 5, name: 'Freitag' },
|
||||
{ id: 6, name: 'Samstag' },
|
||||
{ id: 7, name: 'Sonntag' }
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
@@ -204,40 +214,31 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
<h3>Neue Schicht hinzufügen</h3>
|
||||
<div style={{ display: 'grid', gap: '15px', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}>
|
||||
<div>
|
||||
<label>Datum</label>
|
||||
<input
|
||||
type="date"
|
||||
value={newShift.date}
|
||||
onChange={(e) => setNewShift({ ...newShift, date: e.target.value })}
|
||||
<label>Wochentag</label>
|
||||
<select
|
||||
value={newShift.dayOfWeek}
|
||||
onChange={(e) => setNewShift({ ...newShift, dayOfWeek: parseInt(e.target.value) })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
>
|
||||
{daysOfWeek.map(day => (
|
||||
<option key={day.id} value={day.id}>{day.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label>Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newShift.name}
|
||||
onChange={(e) => setNewShift({ ...newShift, name: e.target.value })}
|
||||
<label>Zeit-Slot</label>
|
||||
<select
|
||||
value={newShift.timeSlotId}
|
||||
onChange={(e) => setNewShift({ ...newShift, timeSlotId: e.target.value })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>Startzeit</label>
|
||||
<input
|
||||
type="time"
|
||||
value={newShift.startTime}
|
||||
onChange={(e) => setNewShift({ ...newShift, startTime: e.target.value })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>Endzeit</label>
|
||||
<input
|
||||
type="time"
|
||||
value={newShift.endTime}
|
||||
onChange={(e) => setNewShift({ ...newShift, endTime: e.target.value })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
>
|
||||
<option value="">Bitte auswählen...</option>
|
||||
{shiftPlan.timeSlots.map(slot => (
|
||||
<option key={slot.id} value={slot.id}>
|
||||
{slot.name} ({slot.startTime}-{slot.endTime})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label>Benötigte Mitarbeiter</label>
|
||||
@@ -252,7 +253,7 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
</div>
|
||||
<button
|
||||
onClick={handleAddShift}
|
||||
disabled={!newShift.date || !newShift.name || !newShift.startTime || !newShift.endTime}
|
||||
disabled={!newShift.timeSlotId || !newShift.requiredEmployees}
|
||||
style={{
|
||||
marginTop: '15px',
|
||||
padding: '8px 16px',
|
||||
@@ -269,140 +270,131 @@ const ShiftPlanEdit: React.FC = () => {
|
||||
|
||||
{/* Existing shifts */}
|
||||
<div style={{ display: 'grid', gap: '20px' }}>
|
||||
{Object.entries(shiftsByDate).map(([date, shifts]) => (
|
||||
<div key={date} style={{
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '8px',
|
||||
padding: '20px',
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
||||
}}>
|
||||
<h3 style={{ marginTop: 0 }}>{new Date(date).toLocaleDateString('de-DE', { weekday: 'long', day: '2-digit', month: '2-digit', year: 'numeric' })}</h3>
|
||||
<div style={{ display: 'grid', gap: '15px' }}>
|
||||
{shifts.map(shift => (
|
||||
<div key={shift.id} style={{
|
||||
backgroundColor: '#f8f9fa',
|
||||
padding: '15px',
|
||||
borderRadius: '6px',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.05)'
|
||||
}}>
|
||||
{editingShift?.id === shift.id ? (
|
||||
<div style={{ display: 'grid', gap: '10px', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}>
|
||||
<div>
|
||||
<label>Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={editingShift.name}
|
||||
onChange={(e) => setEditingShift({ ...editingShift, name: e.target.value })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>Startzeit</label>
|
||||
<input
|
||||
type="time"
|
||||
value={editingShift.startTime}
|
||||
onChange={(e) => setEditingShift({ ...editingShift, startTime: e.target.value })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>Endzeit</label>
|
||||
<input
|
||||
type="time"
|
||||
value={editingShift.endTime}
|
||||
onChange={(e) => setEditingShift({ ...editingShift, endTime: e.target.value })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>Benötigte Mitarbeiter</label>
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
value={editingShift.requiredEmployees}
|
||||
onChange={(e) => setEditingShift({ ...editingShift, requiredEmployees: parseInt(e.target.value) })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '10px', alignItems: 'flex-end' }}>
|
||||
<button
|
||||
onClick={() => handleUpdateShift(editingShift)}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#2ecc71',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setEditingShift(null)}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#95a5a6',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
{daysOfWeek.map(day => {
|
||||
const shifts = shiftsByDay[day.id] || [];
|
||||
if (shifts.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div key={day.id} style={{
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '8px',
|
||||
padding: '20px',
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
||||
}}>
|
||||
<h3 style={{ marginTop: 0 }}>{day.name}</h3>
|
||||
<div style={{ display: 'grid', gap: '15px' }}>
|
||||
{shifts.map(shift => {
|
||||
const timeSlot = shiftPlan.timeSlots.find(ts => ts.id === shift.timeSlotId);
|
||||
return (
|
||||
<div key={shift.id} style={{
|
||||
backgroundColor: '#f8f9fa',
|
||||
padding: '15px',
|
||||
borderRadius: '6px',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.05)'
|
||||
}}>
|
||||
{editingShift?.id === shift.id ? (
|
||||
<div style={{ display: 'grid', gap: '10px', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}>
|
||||
<div>
|
||||
<label>Zeit-Slot</label>
|
||||
<select
|
||||
value={editingShift.timeSlotId}
|
||||
onChange={(e) => setEditingShift({ ...editingShift, timeSlotId: e.target.value })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
>
|
||||
{shiftPlan.timeSlots.map(slot => (
|
||||
<option key={slot.id} value={slot.id}>
|
||||
{slot.name} ({slot.startTime}-{slot.endTime})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label>Benötigte Mitarbeiter</label>
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
value={editingShift.requiredEmployees}
|
||||
onChange={(e) => setEditingShift({ ...editingShift, requiredEmployees: parseInt(e.target.value) })}
|
||||
style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '10px', alignItems: 'flex-end' }}>
|
||||
<button
|
||||
onClick={() => handleUpdateShift(editingShift)}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#2ecc71',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setEditingShift(null)}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#95a5a6',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div style={{ fontWeight: 'bold', marginBottom: '5px' }}>
|
||||
{timeSlot?.name} ({timeSlot?.startTime?.substring(0, 5)} - {timeSlot?.endTime?.substring(0, 5)})
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div style={{ fontSize: '14px', color: '#666' }}>
|
||||
<span>Benötigte Mitarbeiter: {shift.requiredEmployees}</span>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
onClick={() => setEditingShift(shift)}
|
||||
style={{
|
||||
padding: '6px 12px',
|
||||
backgroundColor: '#f1c40f',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
marginRight: '8px'
|
||||
}}
|
||||
>
|
||||
Bearbeiten
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDeleteShift(shift.id)}
|
||||
style={{
|
||||
padding: '6px 12px',
|
||||
backgroundColor: '#e74c3c',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Löschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div style={{ fontWeight: 'bold', marginBottom: '5px' }}>
|
||||
{shift.name}
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div style={{ fontSize: '14px', color: '#666' }}>
|
||||
<span>Zeit: {shift.startTime.substring(0, 5)} - {shift.endTime.substring(0, 5)}</span>
|
||||
<span style={{ margin: '0 15px' }}>|</span>
|
||||
<span>Benötigte Mitarbeiter: {shift.requiredEmployees}</span>
|
||||
<span style={{ margin: '0 15px' }}>|</span>
|
||||
<span>Zugewiesen: {shift.assignedEmployees.length}/{shift.requiredEmployees}</span>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
onClick={() => setEditingShift(shift)}
|
||||
style={{
|
||||
padding: '6px 12px',
|
||||
backgroundColor: '#f1c40f',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
marginRight: '8px'
|
||||
}}
|
||||
>
|
||||
Bearbeiten
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDeleteShift(shift.id)}
|
||||
style={{
|
||||
padding: '6px 12px',
|
||||
backgroundColor: '#e74c3c',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Löschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user