mirror of
https://github.com/donpat1to/Schichtenplaner.git
synced 2025-11-30 22:45:46 +01:00
added scheduledShiftController in backend; fixed API routes for scheduleController
This commit is contained in:
111
backend/src/controllers/scheduledShiftController.ts
Normal file
111
backend/src/controllers/scheduledShiftController.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
// backend/src/controllers/scheduledShiftController.ts
|
||||||
|
import { Request, Response } from 'express';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import bcrypt from 'bcryptjs';
|
||||||
|
import { db } from '../services/databaseService.js';
|
||||||
|
import { AuthRequest } from '../middleware/auth.js';
|
||||||
|
import { CreateEmployeeRequest } from '../models/Employee.js';
|
||||||
|
|
||||||
|
export const getScheduledShiftsFromPlan = async (req: AuthRequest, res: Response): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const { planId } = req.params;
|
||||||
|
|
||||||
|
const shifts = await db.all(
|
||||||
|
`SELECT * FROM scheduled_shifts WHERE plan_id = ? ORDER BY date, time_slot_id`,
|
||||||
|
[planId]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Parse JSON arrays safely
|
||||||
|
const parsedShifts = shifts.map((shift: any) => {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
...shift,
|
||||||
|
assigned_employees: JSON.parse(shift.assigned_employees || '[]')
|
||||||
|
};
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('Error parsing assigned_employees:', parseError);
|
||||||
|
return {
|
||||||
|
...shift,
|
||||||
|
assigned_employees: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json(parsedShifts);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching scheduled shifts:', error);
|
||||||
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getScheduledShift = async (req: AuthRequest, res: Response): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
const shift = await db.get(
|
||||||
|
'SELECT * FROM scheduled_shifts WHERE id = ?',
|
||||||
|
[id]
|
||||||
|
) as any;
|
||||||
|
|
||||||
|
if (!shift) {
|
||||||
|
res.status(404).json({ error: 'Scheduled shift not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse JSON array
|
||||||
|
const parsedShift = {
|
||||||
|
...shift,
|
||||||
|
assigned_employees: JSON.parse(shift.assigned_employees || '[]')
|
||||||
|
};
|
||||||
|
|
||||||
|
res.json(parsedShift);
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Error fetching scheduled shift:', error);
|
||||||
|
res.status(500).json({ error: 'Internal server error: ' + error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateScheduledShift = async (req: AuthRequest, res: Response): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { assignedEmployees } = req.body;
|
||||||
|
|
||||||
|
console.log('🔄 Updating scheduled shift:', {
|
||||||
|
id,
|
||||||
|
assignedEmployees,
|
||||||
|
body: req.body
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!Array.isArray(assignedEmployees)) {
|
||||||
|
res.status(400).json({ error: 'assignedEmployees must be an array' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if shift exists
|
||||||
|
const existingShift = await db.get(
|
||||||
|
'SELECT id FROM scheduled_shifts WHERE id = ?',
|
||||||
|
[id]
|
||||||
|
) as any;
|
||||||
|
|
||||||
|
if (!existingShift) {
|
||||||
|
console.error('❌ Scheduled shift not found:', id);
|
||||||
|
res.status(404).json({ error: `Scheduled shift ${id} not found` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the shift
|
||||||
|
const result = await db.run(
|
||||||
|
'UPDATE scheduled_shifts SET assigned_employees = ? WHERE id = ?',
|
||||||
|
[JSON.stringify(assignedEmployees), id]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('✅ Scheduled shift updated successfully');
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: 'Scheduled shift updated successfully',
|
||||||
|
id: id,
|
||||||
|
assignedEmployees: assignedEmployees
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('❌ Error updating scheduled shift:', error);
|
||||||
|
res.status(500).json({ error: 'Internal server error: ' + error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,117 +1,25 @@
|
|||||||
// backend/src/routes/scheduledShifts.ts - COMPLETE REWRITE
|
// backend/src/routes/scheduledShifts.ts - COMPLETE REWRITE
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { authMiddleware, requireRole } from '../middleware/auth.js';
|
import { authMiddleware, requireRole } from '../middleware/auth.js';
|
||||||
import { db } from '../services/databaseService.js';
|
import { getScheduledShiftsFromPlan, getScheduledShift, updateScheduledShift } from '../controllers/scheduledShiftController.js';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.use(authMiddleware);
|
router.use(authMiddleware);
|
||||||
|
|
||||||
|
// Add a simple test route first
|
||||||
|
/*router.get('/test', (req, res) => {
|
||||||
|
console.log('✅ /api/scheduled-shifts/test route hit');
|
||||||
|
res.json({ message: 'Scheduled shifts router is working!' });
|
||||||
|
});*/
|
||||||
|
|
||||||
// GET all scheduled shifts for a plan (for debugging)
|
// GET all scheduled shifts for a plan (for debugging)
|
||||||
router.get('/plan/:planId', async (req, res) => {
|
router.get('/plan/:planId', requireRole(['admin']), getScheduledShiftsFromPlan);
|
||||||
try {
|
|
||||||
const { planId } = req.params;
|
|
||||||
|
|
||||||
const shifts = await db.all(
|
|
||||||
`SELECT * FROM scheduled_shifts WHERE plan_id = ? ORDER BY date, time_slot_id`,
|
|
||||||
[planId]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Parse JSON arrays safely
|
|
||||||
const parsedShifts = shifts.map((shift: any) => {
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
...shift,
|
|
||||||
assigned_employees: JSON.parse(shift.assigned_employees || '[]')
|
|
||||||
};
|
|
||||||
} catch (parseError) {
|
|
||||||
console.error('Error parsing assigned_employees:', parseError);
|
|
||||||
return {
|
|
||||||
...shift,
|
|
||||||
assigned_employees: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
res.json(parsedShifts);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching scheduled shifts:', error);
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// GET specific scheduled shift
|
// GET specific scheduled shift
|
||||||
router.get('/:id', async (req, res) => {
|
router.get('/:id', requireRole(['admin']), getScheduledShift);
|
||||||
try {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const shift = await db.get(
|
|
||||||
'SELECT * FROM scheduled_shifts WHERE id = ?',
|
|
||||||
[id]
|
|
||||||
) as any;
|
|
||||||
|
|
||||||
if (!shift) {
|
|
||||||
return res.status(404).json({ error: 'Scheduled shift not found' });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse JSON array
|
|
||||||
const parsedShift = {
|
|
||||||
...shift,
|
|
||||||
assigned_employees: JSON.parse(shift.assigned_employees || '[]')
|
|
||||||
};
|
|
||||||
|
|
||||||
res.json(parsedShift);
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('Error fetching scheduled shift:', error);
|
|
||||||
res.status(500).json({ error: 'Internal server error: ' + error.message });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// UPDATE scheduled shift
|
// UPDATE scheduled shift
|
||||||
router.put('/:id', requireRole(['admin', 'instandhalter']), async (req, res) => {
|
router.put('/:id', requireRole(['admin']), updateScheduledShift);
|
||||||
try {
|
|
||||||
const { id } = req.params;
|
|
||||||
const { assignedEmployees } = req.body;
|
|
||||||
|
|
||||||
console.log('🔄 Updating scheduled shift:', {
|
|
||||||
id,
|
|
||||||
assignedEmployees,
|
|
||||||
body: req.body
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!Array.isArray(assignedEmployees)) {
|
|
||||||
return res.status(400).json({ error: 'assignedEmployees must be an array' });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if shift exists
|
|
||||||
const existingShift = await db.get(
|
|
||||||
'SELECT id FROM scheduled_shifts WHERE id = ?',
|
|
||||||
[id]
|
|
||||||
) as any;
|
|
||||||
|
|
||||||
if (!existingShift) {
|
|
||||||
console.error('❌ Scheduled shift not found:', id);
|
|
||||||
return res.status(404).json({ error: `Scheduled shift ${id} not found` });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the shift
|
|
||||||
const result = await db.run(
|
|
||||||
'UPDATE scheduled_shifts SET assigned_employees = ? WHERE id = ?',
|
|
||||||
[JSON.stringify(assignedEmployees), id]
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('✅ Scheduled shift updated successfully');
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
message: 'Scheduled shift updated successfully',
|
|
||||||
id: id,
|
|
||||||
assignedEmployees: assignedEmployees
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('❌ Error updating scheduled shift:', error);
|
|
||||||
res.status(500).json({ error: 'Internal server error: ' + error.message });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
@@ -8,7 +8,7 @@ import authRoutes from './routes/auth.js';
|
|||||||
import employeeRoutes from './routes/employees.js';
|
import employeeRoutes from './routes/employees.js';
|
||||||
import shiftPlanRoutes from './routes/shiftPlans.js';
|
import shiftPlanRoutes from './routes/shiftPlans.js';
|
||||||
import setupRoutes from './routes/setup.js';
|
import setupRoutes from './routes/setup.js';
|
||||||
import scheduledShiftsRouter from './routes/scheduledShifts.js';
|
import scheduledShiftsRoutes from './routes/scheduledShifts.js';
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = 3002;
|
const PORT = 3002;
|
||||||
@@ -22,7 +22,7 @@ app.use('/api/setup', setupRoutes);
|
|||||||
app.use('/api/auth', authRoutes);
|
app.use('/api/auth', authRoutes);
|
||||||
app.use('/api/employees', employeeRoutes);
|
app.use('/api/employees', employeeRoutes);
|
||||||
app.use('/api/shift-plans', shiftPlanRoutes);
|
app.use('/api/shift-plans', shiftPlanRoutes);
|
||||||
app.use('/api/scheduled-shifts', scheduledShiftsRouter);
|
app.use('/api/scheduled-shifts', scheduledShiftsRoutes);
|
||||||
|
|
||||||
// Error handling middleware should come after routes
|
// Error handling middleware should come after routes
|
||||||
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
|
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useParams, useNavigate } from 'react-router-dom';
|
|||||||
import { useAuth } from '../../contexts/AuthContext';
|
import { useAuth } from '../../contexts/AuthContext';
|
||||||
import { shiftPlanService } from '../../services/shiftPlanService';
|
import { shiftPlanService } from '../../services/shiftPlanService';
|
||||||
import { employeeService } from '../../services/employeeService';
|
import { employeeService } from '../../services/employeeService';
|
||||||
import { ShiftAssignmentService, AssignmentResult } from '../../services/shiftAssignmentService';
|
import { shiftAssignmentService, ShiftAssignmentService, AssignmentResult } from '../../services/shiftAssignmentService';
|
||||||
import { ShiftPlan, TimeSlot } from '../../models/ShiftPlan';
|
import { ShiftPlan, TimeSlot } from '../../models/ShiftPlan';
|
||||||
import { Employee, EmployeeAvailability } from '../../models/Employee';
|
import { Employee, EmployeeAvailability } from '../../models/Employee';
|
||||||
import { useNotification } from '../../contexts/NotificationContext';
|
import { useNotification } from '../../contexts/NotificationContext';
|
||||||
@@ -138,10 +138,10 @@ const ShiftPlanView: React.FC = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// First, verify the shift exists
|
// First, verify the shift exists
|
||||||
await shiftPlanService.getScheduledShift(scheduledShift.id);
|
await shiftAssignmentService.getScheduledShift(scheduledShift.id);
|
||||||
|
|
||||||
// Then update it
|
// Then update it
|
||||||
await shiftPlanService.updateScheduledShift(scheduledShift.id, {
|
await shiftAssignmentService.updateScheduledShift(scheduledShift.id, {
|
||||||
assignedEmployees
|
assignedEmployees
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -254,36 +254,6 @@ const ShiftPlanView: React.FC = () => {
|
|||||||
|
|
||||||
const timetableData = getTimetableData();
|
const timetableData = getTimetableData();
|
||||||
|
|
||||||
const debugApiEndpoints = async () => {
|
|
||||||
if (!shiftPlan) return;
|
|
||||||
|
|
||||||
console.log('🔍 Testing API endpoints for plan:', shiftPlan.id);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Test the scheduled shifts endpoint
|
|
||||||
const shifts = await shiftPlanService.getScheduledShiftsForPlan(shiftPlan.id);
|
|
||||||
console.log('✅ GET /api/scheduled-shifts/plan/:planId works:', shifts.length, 'shifts found');
|
|
||||||
|
|
||||||
if (shifts.length > 0) {
|
|
||||||
const firstShift = shifts[0];
|
|
||||||
console.log('🔍 First shift:', firstShift);
|
|
||||||
|
|
||||||
// Test updating the first shift
|
|
||||||
try {
|
|
||||||
await shiftPlanService.updateScheduledShift(firstShift.id, {
|
|
||||||
assignedEmployees: ['test-employee']
|
|
||||||
});
|
|
||||||
console.log('✅ PUT /api/scheduled-shifts/:id works');
|
|
||||||
} catch (updateError) {
|
|
||||||
console.error('❌ PUT /api/scheduled-shifts/:id failed:', updateError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ GET /api/scheduled-shifts/plan/:planId failed:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: '20px' }}>
|
<div style={{ padding: '20px' }}>
|
||||||
{/* Existing header code... */}
|
{/* Existing header code... */}
|
||||||
@@ -460,21 +430,6 @@ const ShiftPlanView: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{publishing ? 'Veröffentliche...' : 'Veröffentlichen'}
|
{publishing ? 'Veröffentliche...' : 'Veröffentlichen'}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={debugApiEndpoints}
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
backgroundColor: '#f39c12',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
marginRight: '10px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Test API Endpoints
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
// frontend/src/services/shiftAssignmentService.ts - WEEKLY PATTERN VERSION
|
// frontend/src/services/shiftAssignmentService.ts - WEEKLY PATTERN VERSION
|
||||||
import { ShiftPlan, ScheduledShift } from '../models/ShiftPlan';
|
import { ShiftPlan, ScheduledShift } from '../models/ShiftPlan';
|
||||||
import { Employee, EmployeeAvailability } from '../models/Employee';
|
import { Employee, EmployeeAvailability } from '../models/Employee';
|
||||||
|
import { authService } from './authService';
|
||||||
|
|
||||||
|
const API_BASE_URL = 'http://localhost:3002/api/scheduled-shifts';
|
||||||
|
|
||||||
export interface AssignmentResult {
|
export interface AssignmentResult {
|
||||||
assignments: { [shiftId: string]: string[] };
|
assignments: { [shiftId: string]: string[] };
|
||||||
@@ -15,7 +18,117 @@ export interface WeeklyPattern {
|
|||||||
weekNumber: number;
|
weekNumber: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to get auth headers
|
||||||
|
const getAuthHeaders = () => {
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
return {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...(token && { 'Authorization': `Bearer ${token}` })
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export class ShiftAssignmentService {
|
export class ShiftAssignmentService {
|
||||||
|
async updateScheduledShift(id: string, updates: { assignedEmployees: string[] }): Promise<void> {
|
||||||
|
try {
|
||||||
|
console.log('🔄 Updating scheduled shift via API:', { id, updates });
|
||||||
|
|
||||||
|
const response = await fetch(`${API_BASE_URL}/${id}`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...authService.getAuthHeaders()
|
||||||
|
},
|
||||||
|
body: JSON.stringify(updates)
|
||||||
|
});
|
||||||
|
|
||||||
|
// First, check if we got any response
|
||||||
|
if (!response.ok) {
|
||||||
|
// Try to get error message from response
|
||||||
|
const responseText = await response.text();
|
||||||
|
console.error('❌ Server response:', responseText);
|
||||||
|
|
||||||
|
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
||||||
|
|
||||||
|
// Try to parse as JSON if possible
|
||||||
|
try {
|
||||||
|
const errorData = JSON.parse(responseText);
|
||||||
|
errorMessage = errorData.error || errorMessage;
|
||||||
|
} catch (e) {
|
||||||
|
// If not JSON, use the text as is
|
||||||
|
errorMessage = responseText || errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to parse successful response
|
||||||
|
const responseText = await response.text();
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = responseText ? JSON.parse(responseText) : {};
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('⚠️ Response was not JSON, but request succeeded');
|
||||||
|
result = { message: 'Update successful' };
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ Scheduled shift updated successfully:', result);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error updating scheduled shift:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getScheduledShift(id: string): Promise<any> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/${id}`, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const responseText = await response.text();
|
||||||
|
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const errorData = JSON.parse(responseText);
|
||||||
|
errorMessage = errorData.error || errorMessage;
|
||||||
|
} catch (e) {
|
||||||
|
errorMessage = responseText || errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseText = await response.text();
|
||||||
|
return responseText ? JSON.parse(responseText) : {};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching scheduled shift:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New method to get all scheduled shifts for a plan
|
||||||
|
async getScheduledShiftsForPlan(planId: string): Promise<ScheduledShift[]> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/plan/${planId}`, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch scheduled shifts: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching scheduled shifts for plan:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static async assignShifts(
|
static async assignShifts(
|
||||||
shiftPlan: ShiftPlan,
|
shiftPlan: ShiftPlan,
|
||||||
@@ -403,4 +516,6 @@ export class ShiftAssignmentService {
|
|||||||
const date = new Date(dateString);
|
const date = new Date(dateString);
|
||||||
return date.getDay() === 0 ? 7 : date.getDay();
|
return date.getDay() === 0 ? 7 : date.getDay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const shiftAssignmentService = new ShiftAssignmentService();
|
||||||
@@ -186,105 +186,4 @@ export const shiftPlanService = {
|
|||||||
description: preset.description
|
description: preset.description
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
async updateScheduledShift(id: string, updates: { assignedEmployees: string[] }): Promise<void> {
|
|
||||||
try {
|
|
||||||
console.log('🔄 Updating scheduled shift via API:', { id, updates });
|
|
||||||
|
|
||||||
const response = await fetch(`/api/scheduled-shifts/${id}`, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
|
||||||
},
|
|
||||||
body: JSON.stringify(updates)
|
|
||||||
});
|
|
||||||
|
|
||||||
// First, check if we got any response
|
|
||||||
if (!response.ok) {
|
|
||||||
// Try to get error message from response
|
|
||||||
const responseText = await response.text();
|
|
||||||
console.error('❌ Server response:', responseText);
|
|
||||||
|
|
||||||
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
||||||
|
|
||||||
// Try to parse as JSON if possible
|
|
||||||
try {
|
|
||||||
const errorData = JSON.parse(responseText);
|
|
||||||
errorMessage = errorData.error || errorMessage;
|
|
||||||
} catch (e) {
|
|
||||||
// If not JSON, use the text as is
|
|
||||||
errorMessage = responseText || errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse successful response
|
|
||||||
const responseText = await response.text();
|
|
||||||
let result;
|
|
||||||
try {
|
|
||||||
result = responseText ? JSON.parse(responseText) : {};
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('⚠️ Response was not JSON, but request succeeded');
|
|
||||||
result = { message: 'Update successful' };
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('✅ Scheduled shift updated successfully:', result);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Error updating scheduled shift:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async getScheduledShift(id: string): Promise<any> {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/scheduled-shifts/${id}`, {
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const responseText = await response.text();
|
|
||||||
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const errorData = JSON.parse(responseText);
|
|
||||||
errorMessage = errorData.error || errorMessage;
|
|
||||||
} catch (e) {
|
|
||||||
errorMessage = responseText || errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
const responseText = await response.text();
|
|
||||||
return responseText ? JSON.parse(responseText) : {};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching scheduled shift:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// New method to get all scheduled shifts for a plan
|
|
||||||
async getScheduledShiftsForPlan(planId: string): Promise<ScheduledShift[]> {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/scheduled-shifts/plan/${planId}`, {
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Failed to fetch scheduled shifts: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await response.json();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching scheduled shifts for plan:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user