Zwiscshenstand - laufende Version

Dieser Commit ist enthalten in:
Claude Project Manager
2025-09-27 13:11:39 +02:00
Ursprung 81e57ecff6
Commit 2689cd2d32
30 geänderte Dateien mit 1021 neuen und 459 gelöschten Zeilen

Datei anzeigen

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import api from '../services/api'
import { DeputyAssignment, Employee } from '@skillmate/shared'
import type { DeputyAssignment, Employee } from '@skillmate/shared'
import { useAuthStore } from '../stores/authStore'
export default function DeputyManagement() {

Datei anzeigen

@ -1,5 +1,5 @@
import { useEffect, useState, useCallback } from 'react'
import { OrganizationalUnit, EmployeeUnitAssignment } from '@skillmate/shared'
import type { OrganizationalUnit, EmployeeUnitAssignment } from '@skillmate/shared'
import api from '../services/api'
import { useAuthStore } from '../stores/authStore'

Datei anzeigen

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
import { OrganizationalUnit } from '@skillmate/shared'
import type { OrganizationalUnit } from '@skillmate/shared'
import api from '../services/api'
import { ChevronRight, Building2, Search, X } from 'lucide-react'
@ -277,4 +277,4 @@ export default function OrganizationSelector({ value, onChange, disabled }: Orga
)}
</>
)
}
}

Datei anzeigen

@ -1,4 +1,4 @@
import { UserRole } from '@skillmate/shared'
import type { UserRole } from '@skillmate/shared'
import { useAuthStore } from '../stores/authStore'
// Define role permissions directly to avoid import issues
@ -94,4 +94,4 @@ export function usePermissions() {
user,
isAuthenticated
}
}
}

Datei anzeigen

@ -1,5 +1,5 @@
import axios from 'axios'
import { Employee } from '@skillmate/shared'
import type { Employee } from '@skillmate/shared'
const API_BASE_URL = (import.meta as any).env?.VITE_API_URL || 'http://localhost:3004/api'
@ -31,7 +31,8 @@ export const authApi = {
export const employeeApi = {
getAll: async () => {
const response = await api.get('/employees/public')
// Hole vollständige Liste (berechtigt durch employees:read)
const response = await api.get('/employees')
return response.data.data
},
getById: async (id: string) => {

Datei anzeigen

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { api } from '../services/api'
import { Workspace, Booking, WorkspaceFilter } from '@skillmate/shared'
import type { Workspace, Booking, WorkspaceFilter } from '@skillmate/shared'
export default function DeskBooking() {
const navigate = useNavigate()
@ -257,4 +257,4 @@ export default function DeskBooking() {
</div>
</div>
)
}
}

Datei anzeigen

@ -4,6 +4,7 @@ import type { Employee } from '@skillmate/shared'
import { employeeApi } from '../services/api'
import { SKILL_HIERARCHY, LANGUAGE_LEVELS } from '../data/skillCategories'
import PhotoPreview from '../components/PhotoPreview'
import OrganizationSelector from '../components/OrganizationSelector'
export default function EmployeeForm() {
const navigate = useNavigate()
@ -28,6 +29,8 @@ export default function EmployeeForm() {
languages: [] as string[],
specializations: [] as string[]
})
const [primaryUnitId, setPrimaryUnitId] = useState<string | null>(null)
const [primaryUnitName, setPrimaryUnitName] = useState<string>('')
const [employeePhoto, setEmployeePhoto] = useState<string | null>(null)
const [photoFile, setPhotoFile] = useState<File | null>(null)
@ -178,6 +181,7 @@ export default function EmployeeForm() {
if (!formData.email.trim()) errors.email = 'E-Mail ist erforderlich'
else if (!/\S+@\S+\.\S+/.test(formData.email)) errors.email = 'Ungültige E-Mail-Adresse'
if (!formData.phone.trim()) errors.phone = 'Telefonnummer ist erforderlich'
if (!primaryUnitId) errors.primaryUnitId = 'Organisatorische Einheit ist erforderlich'
setValidationErrors(errors)
return Object.keys(errors).length === 0
@ -220,7 +224,7 @@ export default function EmployeeForm() {
createdBy: 'admin'
}
const result = await employeeApi.create(newEmployee)
const result = await employeeApi.create({ ...newEmployee, primaryUnitId })
const newEmployeeId = result.data.id
// Upload photo if we have one
@ -407,6 +411,23 @@ export default function EmployeeForm() {
)}
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-secondary mb-2">
Organisatorische Einheit (Primär) *
</label>
<OrganizationSelector
value={primaryUnitId || undefined}
onChange={(unitId, unitName) => {
setPrimaryUnitId(unitId)
setPrimaryUnitName(unitName)
}}
/>
<p className="text-tertiary text-sm mt-2">{primaryUnitName || 'Bitte auswählen'}</p>
{validationErrors.primaryUnitId && (
<p className="mt-1 text-sm text-red-600">{validationErrors.primaryUnitId}</p>
)}
</div>
<div>
<label className="block text-sm font-medium text-secondary mb-2">
Telefon *

Datei anzeigen

@ -1,10 +1,10 @@
import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import type { Employee } from '@skillmate/shared'
import { SearchIcon } from '../components/icons'
import EmployeeCard from '../components/EmployeeCard'
import { employeeApi } from '../services/api'
import { useAuthStore } from '../stores/authStore'
import type { Employee } from '@skillmate/shared'
import { usePermissions } from '../hooks/usePermissions'
export default function EmployeeList() {

Datei anzeigen

@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'
import { api } from '../services/api'
import { Workspace, Booking } from '@skillmate/shared'
import type { Workspace, Booking } from '@skillmate/shared'
interface WorkspaceWithStatus extends Workspace {
isBooked?: boolean
@ -248,4 +248,4 @@ export default function FloorPlan() {
</div>
</div>
)
}
}

Datei anzeigen

@ -962,4 +962,4 @@ export default function TeamZusammenstellung() {
)}
</div>
)
}
}

Datei anzeigen

@ -11,16 +11,33 @@ export default defineConfig({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production'),
'process.platform': JSON.stringify('win32')
},
server: {
port: 5173,
strictPort: true,
fs: {
// erlaubt Zugriff auf Monorepo-Nachbarordner (z. B. ../shared)
allow: ['..']
}
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
// erhöht Kompatibilität mit verlinkten/local deps
preserveSymlinks: true,
},
optimizeDeps: {
include: ['@skillmate/shared'],
},
build: {
outDir: 'dist',
emptyOutDir: true,
commonjsOptions: {
include: [/node_modules/, /@skillmate\/shared/],
transformMixedEsModules: true,
},
rollupOptions: {
external: ['electron'],
}
},
})
})