328 lines
10 KiB
JavaScript
328 lines
10 KiB
JavaScript
import { useState, useEffect } from 'react'
|
|
import { FaTimes } from 'react-icons/fa'
|
|
import { useAuth } from '../context/AuthContext'
|
|
|
|
const SERVICE_TYPES = ['Remote', 'On Site', 'Off Site', 'COMMENT']
|
|
|
|
const STATUS_OPTIONS = [
|
|
'Open',
|
|
'Closed',
|
|
'Awaiting',
|
|
'Added Info',
|
|
'Occupied',
|
|
'Halted',
|
|
'Cancelled',
|
|
'Aborted',
|
|
'Assigned',
|
|
'In Test'
|
|
]
|
|
|
|
const RESPONSE_LEVELS = [
|
|
'KEY USER',
|
|
'1st Level',
|
|
'2nd Level',
|
|
'3rd Level',
|
|
'FS/FE',
|
|
'24/7',
|
|
'TECH MGMT',
|
|
'Backoffice',
|
|
'BUSI MGMT',
|
|
'n/a'
|
|
]
|
|
|
|
export default function CreateWorksheetModal({ isOpen, onClose, workorder, onCreate }) {
|
|
const { user } = useAuth()
|
|
const today = new Date().toLocaleDateString('de-DE', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric'
|
|
})
|
|
|
|
const [formData, setFormData] = useState({
|
|
serviceType: 'Remote',
|
|
newStatus: workorder?.status || 'Open',
|
|
newResponseLevel: workorder?.responseLevel || '',
|
|
totalTime: 0,
|
|
startDate: today,
|
|
startTime: '',
|
|
endDate: today,
|
|
endTime: '',
|
|
details: '',
|
|
isComment: false
|
|
})
|
|
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState('')
|
|
const [autoCalculate, setAutoCalculate] = useState(true)
|
|
|
|
// Reset form wenn Modal geöffnet wird
|
|
useEffect(() => {
|
|
if (isOpen && workorder) {
|
|
setFormData({
|
|
serviceType: 'Remote',
|
|
newStatus: workorder.status || 'Open',
|
|
newResponseLevel: workorder.responseLevel || '',
|
|
totalTime: 0,
|
|
startDate: today,
|
|
startTime: '',
|
|
endDate: today,
|
|
endTime: '',
|
|
details: '',
|
|
isComment: false
|
|
})
|
|
setError('')
|
|
setAutoCalculate(true)
|
|
}
|
|
}, [isOpen, workorder, today])
|
|
|
|
// Automatische Zeitberechnung
|
|
useEffect(() => {
|
|
if (autoCalculate && formData.startTime && formData.endTime && !formData.isComment) {
|
|
try {
|
|
const startHour = parseInt(formData.startTime.substring(0, 2))
|
|
const startMin = parseInt(formData.startTime.substring(2, 4))
|
|
const endHour = parseInt(formData.endTime.substring(0, 2))
|
|
const endMin = parseInt(formData.endTime.substring(2, 4))
|
|
|
|
if (!isNaN(startHour) && !isNaN(startMin) && !isNaN(endHour) && !isNaN(endMin)) {
|
|
const startTotal = startHour * 60 + startMin
|
|
const endTotal = endHour * 60 + endMin
|
|
|
|
let diff = endTotal - startTotal
|
|
if (diff < 0) {
|
|
diff += 24 * 60 // Overnight
|
|
}
|
|
|
|
setFormData(prev => ({ ...prev, totalTime: diff }))
|
|
}
|
|
} catch (err) {
|
|
// Ignoriere Fehler
|
|
}
|
|
}
|
|
}, [formData.startTime, formData.endTime, formData.isComment, autoCalculate])
|
|
|
|
const handleChange = (field, value) => {
|
|
setFormData(prev => ({ ...prev, [field]: value }))
|
|
|
|
// Wenn totalTime manuell geändert wird, deaktiviere Auto-Berechnung
|
|
if (field === 'totalTime') {
|
|
setAutoCalculate(false)
|
|
}
|
|
}
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault()
|
|
setLoading(true)
|
|
setError('')
|
|
|
|
try {
|
|
if (!formData.details.trim()) {
|
|
setError('Bitte Details eingeben')
|
|
setLoading(false)
|
|
return
|
|
}
|
|
|
|
const worksheetData = {
|
|
woid: workorder.woid,
|
|
workorderId: workorder.$id,
|
|
serviceType: formData.serviceType,
|
|
oldStatus: workorder.status,
|
|
newStatus: formData.newStatus,
|
|
oldResponseLevel: workorder.responseLevel || '',
|
|
newResponseLevel: formData.newResponseLevel,
|
|
totalTime: formData.isComment ? 0 : parseInt(formData.totalTime) || 0,
|
|
startDate: formData.startDate,
|
|
startTime: formData.startTime,
|
|
endDate: formData.endDate,
|
|
endTime: formData.endTime,
|
|
details: formData.details,
|
|
isComment: formData.isComment,
|
|
employeeShort: user?.prefs?.shortCode || '' // Aus User-Preferences
|
|
}
|
|
|
|
const result = await onCreate(worksheetData, user)
|
|
|
|
if (result.success) {
|
|
onClose()
|
|
} else {
|
|
setError(result.error || 'Fehler beim Erstellen des Worksheets')
|
|
}
|
|
} catch (err) {
|
|
console.error('Error creating worksheet:', err)
|
|
setError(err.message || 'Ein unerwarteter Fehler ist aufgetreten')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
if (!isOpen || !workorder) return null
|
|
|
|
return (
|
|
<div className="overlay">
|
|
<span className="overlay-close" onClick={onClose}>
|
|
<FaTimes />
|
|
</span>
|
|
<div className="overlay-content">
|
|
<h2 className="mb-2">Create New Worksheet - WOID {workorder.woid}</h2>
|
|
|
|
{error && (
|
|
<div className="bg-red text-white p-2 mb-2" style={{ borderRadius: '4px' }}>
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
<div className="row">
|
|
<div className="col col-6">
|
|
<div className="form-group">
|
|
<label className="form-label">Service Type</label>
|
|
<select
|
|
className="form-control"
|
|
value={formData.serviceType}
|
|
onChange={(e) => handleChange('serviceType', e.target.value)}
|
|
required
|
|
>
|
|
{SERVICE_TYPES.map(type => (
|
|
<option key={type} value={type}>{type}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label">New Status</label>
|
|
<select
|
|
className="form-control"
|
|
value={formData.newStatus}
|
|
onChange={(e) => handleChange('newStatus', e.target.value)}
|
|
required
|
|
>
|
|
{STATUS_OPTIONS.map(status => (
|
|
<option key={status} value={status}>{status}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label">New Response Level</label>
|
|
<select
|
|
className="form-control"
|
|
value={formData.newResponseLevel}
|
|
onChange={(e) => handleChange('newResponseLevel', e.target.value)}
|
|
>
|
|
<option value="">Select Response Level</option>
|
|
{RESPONSE_LEVELS.map(level => (
|
|
<option key={level} value={level}>{level}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
<input
|
|
type="checkbox"
|
|
checked={formData.isComment}
|
|
onChange={(e) => handleChange('isComment', e.target.checked)}
|
|
/>
|
|
Nur Kommentar (keine Arbeitszeit)
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="col col-6">
|
|
<div className="form-group">
|
|
<label className="form-label">Total Time (Minuten)</label>
|
|
<input
|
|
type="number"
|
|
className="form-control"
|
|
min="0"
|
|
step="15"
|
|
value={formData.totalTime}
|
|
onChange={(e) => handleChange('totalTime', e.target.value)}
|
|
disabled={formData.isComment}
|
|
placeholder="0"
|
|
/>
|
|
<small style={{ color: '#a0aec0', fontSize: '12px' }}>
|
|
{autoCalculate && formData.startTime && formData.endTime
|
|
? '✓ Automatisch berechnet'
|
|
: 'Manuell eingeben'}
|
|
</small>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label">Start Date</label>
|
|
<input
|
|
type="text"
|
|
className="form-control"
|
|
placeholder="dd.mm.yyyy"
|
|
value={formData.startDate}
|
|
onChange={(e) => handleChange('startDate', e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label">End Date</label>
|
|
<input
|
|
type="text"
|
|
className="form-control"
|
|
placeholder="dd.mm.yyyy"
|
|
value={formData.endDate}
|
|
onChange={(e) => handleChange('endDate', e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label">Start Time</label>
|
|
<input
|
|
type="text"
|
|
className="form-control"
|
|
placeholder="hhmm"
|
|
value={formData.startTime}
|
|
onChange={(e) => handleChange('startTime', e.target.value)}
|
|
maxLength="4"
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label">End Time</label>
|
|
<input
|
|
type="text"
|
|
className="form-control"
|
|
placeholder="hhmm"
|
|
value={formData.endTime}
|
|
onChange={(e) => handleChange('endTime', e.target.value)}
|
|
maxLength="4"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label">Action Details</label>
|
|
<textarea
|
|
className="form-control"
|
|
rows={5}
|
|
placeholder="Beschreibe die durchgeführten Arbeiten..."
|
|
value={formData.details}
|
|
onChange={(e) => handleChange('details', e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="text-center mt-2">
|
|
<button
|
|
type="submit"
|
|
className="btn btn-dark"
|
|
disabled={loading}
|
|
>
|
|
{loading ? 'Creating...' : 'CREATE NOW'}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|