Ich habe gestern vergessen zu pushen
Dieser Commit ist enthalten in:
@ -83,13 +83,13 @@ export const encryptedDb = {
|
||||
|
||||
return db.prepare(`
|
||||
INSERT INTO employees (
|
||||
id, first_name, last_name, employee_number, photo, position,
|
||||
id, first_name, last_name, employee_number, photo, position, official_title,
|
||||
department, email, email_hash, phone, phone_hash, mobile, office, availability,
|
||||
clearance_level, clearance_valid_until, clearance_issued_date,
|
||||
primary_unit_id,
|
||||
created_at, updated_at, created_by
|
||||
) VALUES (
|
||||
@id, @first_name, @last_name, @employee_number, @photo, @position,
|
||||
@id, @first_name, @last_name, @employee_number, @photo, @position, @official_title,
|
||||
@department, @email, @email_hash, @phone, @phone_hash, @mobile, @office, @availability,
|
||||
@clearance_level, @clearance_valid_until, @clearance_issued_date,
|
||||
@primary_unit_id,
|
||||
@ -109,6 +109,7 @@ export const encryptedDb = {
|
||||
// Decrypt sensitive fields
|
||||
return {
|
||||
...employee,
|
||||
official_title: employee.official_title,
|
||||
email: FieldEncryption.decrypt(employee.email),
|
||||
phone: FieldEncryption.decrypt(employee.phone),
|
||||
mobile: FieldEncryption.decrypt(employee.mobile),
|
||||
@ -136,6 +137,7 @@ export const encryptedDb = {
|
||||
|
||||
return {
|
||||
...emp,
|
||||
official_title: emp.official_title,
|
||||
email: safeDecrypt(emp.email),
|
||||
phone: safeDecrypt(emp.phone),
|
||||
mobile: safeDecrypt(emp.mobile),
|
||||
@ -164,6 +166,7 @@ export function initializeSecureDatabase() {
|
||||
employee_number TEXT UNIQUE NOT NULL,
|
||||
photo TEXT,
|
||||
position TEXT NOT NULL,
|
||||
official_title TEXT,
|
||||
department TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
email_hash TEXT,
|
||||
@ -190,6 +193,10 @@ export function initializeSecureDatabase() {
|
||||
if (!hasPrimaryUnitId) {
|
||||
db.exec(`ALTER TABLE employees ADD COLUMN primary_unit_id TEXT`)
|
||||
}
|
||||
const hasOfficialTitle = cols.some(c => c.name === 'official_title')
|
||||
if (!hasOfficialTitle) {
|
||||
db.exec(`ALTER TABLE employees ADD COLUMN official_title TEXT`)
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ export interface EmployeeInput {
|
||||
employeeNumber?: string | null
|
||||
photo?: string | null
|
||||
position?: string
|
||||
officialTitle?: string | null
|
||||
department: string
|
||||
email: string
|
||||
phone?: string | null
|
||||
@ -76,6 +77,7 @@ export function getAllWithDetails(): Employee[] {
|
||||
employeeNumber: (emp.employee_number && !String(emp.employee_number).startsWith('EMP')) ? emp.employee_number : undefined,
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: emp.department,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
@ -136,6 +138,7 @@ function buildEmployeeWithDetails(emp: any): Employee {
|
||||
mobile: emp.mobile,
|
||||
office: emp.office,
|
||||
availability: emp.availability,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
skills: skills.map((s: any) => ({
|
||||
id: s.id,
|
||||
name: s.name,
|
||||
@ -166,6 +169,7 @@ export function createEmployee(input: EmployeeInput, actorUserId: string): { id:
|
||||
const now = new Date().toISOString()
|
||||
const employeeId = uuidv4()
|
||||
const position = input.position || 'Teammitglied'
|
||||
const officialTitle = input.officialTitle || null
|
||||
const phone = input.phone || 'Nicht angegeben'
|
||||
const availability = input.availability || 'available'
|
||||
const employeeNumber = input.employeeNumber || `EMP${Date.now()}`
|
||||
@ -186,6 +190,7 @@ export function createEmployee(input: EmployeeInput, actorUserId: string): { id:
|
||||
employee_number: employeeNumber,
|
||||
photo: input.photo || null,
|
||||
position,
|
||||
official_title: officialTitle,
|
||||
department: input.department,
|
||||
email: input.email,
|
||||
phone,
|
||||
@ -249,14 +254,14 @@ export function updateEmployee(id: string, input: EmployeeInput, actorUserId: st
|
||||
|
||||
db.prepare(`
|
||||
UPDATE employees SET
|
||||
first_name = ?, last_name = ?, position = ?, department = ?,
|
||||
first_name = ?, last_name = ?, position = ?, official_title = ?, department = ?,
|
||||
email = ?, email_hash = ?, phone = ?, phone_hash = ?,
|
||||
mobile = ?, office = ?, availability = ?,
|
||||
clearance_level = ?, clearance_valid_until = ?, clearance_issued_date = ?,
|
||||
updated_at = ?, updated_by = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
input.firstName, input.lastName, input.position || 'Teammitglied', input.department,
|
||||
input.firstName, input.lastName, input.position || 'Teammitglied', input.officialTitle || null, input.department,
|
||||
// encryption handled in secure db layer caller; here store encrypted values already in input? Route prepares with FieldEncryption
|
||||
input.email, // already encrypted by route layer
|
||||
null, // email_hash set by route if needed
|
||||
|
||||
@ -34,7 +34,7 @@ function mapProficiencyToLevel(proficiency: string): 'basic' | 'fluent' | 'nativ
|
||||
router.get('/', authenticate, requirePermission('employees:read'), async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const employees = db.prepare(`
|
||||
SELECT id, first_name, last_name, employee_number, photo, position,
|
||||
SELECT id, first_name, last_name, employee_number, photo, position, official_title,
|
||||
department, email, phone, mobile, office, availability,
|
||||
clearance_level, clearance_valid_until, clearance_issued_date,
|
||||
created_at, updated_at, created_by, updated_by
|
||||
@ -70,6 +70,7 @@ router.get('/', authenticate, requirePermission('employees:read'), async (req: A
|
||||
employeeNumber: emp.employee_number,
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: emp.department,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
@ -116,7 +117,7 @@ router.get('/:id', authenticate, requirePermission('employees:read'), async (req
|
||||
const { id } = req.params
|
||||
|
||||
const emp = db.prepare(`
|
||||
SELECT id, first_name, last_name, employee_number, photo, position,
|
||||
SELECT id, first_name, last_name, employee_number, photo, position, official_title,
|
||||
department, email, phone, mobile, office, availability,
|
||||
clearance_level, clearance_valid_until, clearance_issued_date,
|
||||
created_at, updated_at, created_by, updated_by
|
||||
@ -158,6 +159,7 @@ router.get('/:id', authenticate, requirePermission('employees:read'), async (req
|
||||
employeeNumber: emp.employee_number,
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: emp.department,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
@ -202,6 +204,7 @@ router.post('/',
|
||||
[
|
||||
body('firstName').notEmpty().trim(),
|
||||
body('lastName').notEmpty().trim(),
|
||||
body('officialTitle').optional().trim(),
|
||||
body('email').isEmail(),
|
||||
body('department').notEmpty().trim(),
|
||||
body('organizationUnitId').optional({ checkFalsy: true }).isUUID(),
|
||||
@ -221,7 +224,7 @@ router.post('/',
|
||||
const now = new Date().toISOString()
|
||||
|
||||
const {
|
||||
firstName, lastName, employeeNumber, photo, position,
|
||||
firstName, lastName, employeeNumber, photo, position, officialTitle,
|
||||
department, email, phone, mobile, office, availability,
|
||||
clearance, skills, languages, specializations,
|
||||
userRole, createUser, organizationUnitId, organizationRole
|
||||
@ -253,11 +256,11 @@ router.post('/',
|
||||
// Insert employee with default values for missing fields
|
||||
db.prepare(`
|
||||
INSERT INTO employees (
|
||||
id, first_name, last_name, employee_number, photo, position,
|
||||
id, first_name, last_name, employee_number, photo, position, official_title,
|
||||
department, email, phone, mobile, office, availability, primary_unit_id,
|
||||
clearance_level, clearance_valid_until, clearance_issued_date,
|
||||
created_at, updated_at, created_by
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
employeeId,
|
||||
firstName,
|
||||
@ -265,6 +268,7 @@ router.post('/',
|
||||
employeeNumber || null,
|
||||
photo || null,
|
||||
position || 'Teammitglied', // Default position
|
||||
officialTitle || null,
|
||||
resolvedDepartment,
|
||||
email,
|
||||
phone || 'Nicht angegeben', // Default phone
|
||||
@ -430,6 +434,7 @@ router.put('/:id',
|
||||
body('firstName').notEmpty().trim(),
|
||||
body('lastName').notEmpty().trim(),
|
||||
body('position').notEmpty().trim(),
|
||||
body('officialTitle').optional().trim(),
|
||||
body('department').notEmpty().trim(),
|
||||
body('email').isEmail(),
|
||||
body('phone').notEmpty().trim(),
|
||||
@ -449,7 +454,7 @@ router.put('/:id',
|
||||
const now = new Date().toISOString()
|
||||
|
||||
const {
|
||||
firstName, lastName, position, department, email, phone,
|
||||
firstName, lastName, position, officialTitle, department, email, phone,
|
||||
mobile, office, availability, clearance, skills, languages, specializations
|
||||
} = req.body
|
||||
|
||||
@ -465,13 +470,13 @@ router.put('/:id',
|
||||
// Update employee
|
||||
db.prepare(`
|
||||
UPDATE employees SET
|
||||
first_name = ?, last_name = ?, position = ?, department = ?,
|
||||
first_name = ?, last_name = ?, position = ?, official_title = ?, department = ?,
|
||||
email = ?, phone = ?, mobile = ?, office = ?, availability = ?,
|
||||
clearance_level = ?, clearance_valid_until = ?, clearance_issued_date = ?,
|
||||
updated_at = ?, updated_by = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
firstName, lastName, position, department,
|
||||
firstName, lastName, position, officialTitle || null, department,
|
||||
email, phone, mobile || null, office || null, availability,
|
||||
clearance?.level || null, clearance?.validUntil || null, clearance?.issuedDate || null,
|
||||
now, req.user!.id, id
|
||||
@ -508,6 +513,7 @@ router.put('/:id',
|
||||
firstName,
|
||||
lastName,
|
||||
position,
|
||||
officialTitle: officialTitle || null,
|
||||
department,
|
||||
email,
|
||||
phone,
|
||||
|
||||
@ -121,6 +121,7 @@ router.get('/', authenticate, requirePermission('employees:read'), async (req: A
|
||||
employeeNumber: (emp.employee_number && !String(emp.employee_number).startsWith('EMP')) ? emp.employee_number : undefined,
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: emp.department,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
@ -203,6 +204,7 @@ router.get('/public', authenticate, async (req: AuthRequest, res, next) => {
|
||||
employeeNumber: (emp.employee_number && !String(emp.employee_number).startsWith('EMP')) ? emp.employee_number : undefined,
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: emp.department,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
@ -285,6 +287,7 @@ router.get('/:id', authenticate, requirePermission('employees:read'), async (req
|
||||
employeeNumber: (emp.employee_number && !String(emp.employee_number).startsWith('EMP')) ? emp.employee_number : undefined,
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: emp.department,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
@ -354,7 +357,7 @@ router.post('/',
|
||||
const now = new Date().toISOString()
|
||||
|
||||
const {
|
||||
firstName, lastName, employeeNumber, photo, position = 'Teammitglied',
|
||||
firstName, lastName, employeeNumber, photo, position = 'Teammitglied', officialTitle,
|
||||
department, email, phone = 'Nicht angegeben', mobile, office, availability = 'available',
|
||||
clearance, skills = [], languages = [], specializations = [], userRole, createUser,
|
||||
primaryUnitId, assignmentRole
|
||||
@ -380,6 +383,7 @@ router.post('/',
|
||||
employee_number: finalEmployeeNumber,
|
||||
photo: photo || null,
|
||||
position,
|
||||
official_title: officialTitle || null,
|
||||
department,
|
||||
email,
|
||||
phone,
|
||||
@ -513,6 +517,7 @@ router.post('/',
|
||||
employeeNumber: finalEmployeeNumber,
|
||||
photo: photo || null,
|
||||
position,
|
||||
officialTitle: officialTitle || null,
|
||||
department,
|
||||
email,
|
||||
phone,
|
||||
@ -591,6 +596,7 @@ router.put('/:id',
|
||||
body('firstName').notEmpty().trim().escape(),
|
||||
body('lastName').notEmpty().trim().escape(),
|
||||
body('position').optional().trim().escape(),
|
||||
body('officialTitle').optional().trim().escape(),
|
||||
body('department').notEmpty().trim().escape(),
|
||||
body('email').isEmail().normalizeEmail(),
|
||||
body('phone').optional().trim(),
|
||||
@ -612,7 +618,7 @@ router.put('/:id',
|
||||
const now = new Date().toISOString()
|
||||
|
||||
const {
|
||||
firstName, lastName, position = 'Teammitglied', department, email, phone = 'Nicht angegeben',
|
||||
firstName, lastName, position = 'Teammitglied', officialTitle, department, email, phone = 'Nicht angegeben',
|
||||
mobile, office, availability = 'available', clearance, skills, languages, specializations,
|
||||
employeeNumber
|
||||
} = req.body
|
||||
@ -629,14 +635,14 @@ router.put('/:id',
|
||||
// Update employee with encrypted fields
|
||||
db.prepare(`
|
||||
UPDATE employees SET
|
||||
first_name = ?, last_name = ?, position = ?, department = ?,
|
||||
first_name = ?, last_name = ?, position = ?, official_title = ?, department = ?,
|
||||
email = ?, email_hash = ?, phone = ?, phone_hash = ?,
|
||||
mobile = ?, office = ?, availability = ?,
|
||||
clearance_level = ?, clearance_valid_until = ?, clearance_issued_date = ?,
|
||||
updated_at = ?, updated_by = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
firstName, lastName, position, department,
|
||||
firstName, lastName, position, officialTitle || null, department,
|
||||
FieldEncryption.encrypt(email),
|
||||
FieldEncryption.hash(email),
|
||||
FieldEncryption.encrypt(phone || ''),
|
||||
@ -702,6 +708,7 @@ router.put('/:id',
|
||||
firstName,
|
||||
lastName,
|
||||
position,
|
||||
officialTitle: officialTitle || null,
|
||||
department,
|
||||
email,
|
||||
phone,
|
||||
|
||||
@ -18,6 +18,7 @@ export async function createEmployeeUC(req: Request, body: any, actorUserId: str
|
||||
employeeNumber: body.employeeNumber,
|
||||
photo: body.photo,
|
||||
position: body.position,
|
||||
officialTitle: body.officialTitle,
|
||||
department: body.department,
|
||||
email: body.email,
|
||||
phone: body.phone,
|
||||
@ -40,6 +41,7 @@ export async function createEmployeeUC(req: Request, body: any, actorUserId: str
|
||||
employeeNumber: body.employeeNumber || null,
|
||||
photo: body.photo || null,
|
||||
position: body.position || 'Teammitglied',
|
||||
officialTitle: body.officialTitle || null,
|
||||
department: body.department,
|
||||
email: body.email,
|
||||
phone: body.phone || 'Nicht angegeben',
|
||||
@ -65,6 +67,7 @@ export async function updateEmployeeUC(req: Request, id: string, body: any, acto
|
||||
firstName: body.firstName,
|
||||
lastName: body.lastName,
|
||||
position: body.position,
|
||||
officialTitle: body.officialTitle,
|
||||
department: body.department,
|
||||
email: body.email,
|
||||
phone: body.phone,
|
||||
@ -84,6 +87,7 @@ export async function updateEmployeeUC(req: Request, id: string, body: any, acto
|
||||
firstName: body.firstName,
|
||||
lastName: body.lastName,
|
||||
position: body.position,
|
||||
officialTitle: body.officialTitle,
|
||||
department: body.department,
|
||||
email: body.email,
|
||||
phone: body.phone,
|
||||
|
||||
@ -63,6 +63,11 @@ export default function EmployeeCard({ employee, onClick }: EmployeeCardProps) {
|
||||
<p className="text-body text-secondary">
|
||||
<span className="font-medium">Position:</span> {employee.position}
|
||||
</p>
|
||||
{employee.officialTitle && (
|
||||
<p className="text-body text-secondary">
|
||||
<span className="font-medium">Amtsbezeichnung:</span> {employee.officialTitle}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-body text-secondary">
|
||||
<span className="font-medium">Dienststelle:</span> {employee.department}
|
||||
</p>
|
||||
|
||||
@ -168,6 +168,12 @@ export default function EmployeeDetail() {
|
||||
<span className="text-tertiary">Position:</span>
|
||||
<p className="text-secondary font-medium">{employee.position}</p>
|
||||
</div>
|
||||
{employee.officialTitle && (
|
||||
<div>
|
||||
<span className="text-tertiary">Amtsbezeichnung:</span>
|
||||
<p className="text-secondary font-medium">{employee.officialTitle}</p>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<span className="text-tertiary">Dienststelle:</span>
|
||||
<p className="text-secondary font-medium">{employee.department}</p>
|
||||
|
||||
@ -17,6 +17,7 @@ export default function EmployeeForm() {
|
||||
lastName: '',
|
||||
employeeNumber: '',
|
||||
position: '',
|
||||
officialTitle: '',
|
||||
department: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
@ -219,6 +220,7 @@ export default function EmployeeForm() {
|
||||
validUntil: new Date(new Date().setFullYear(new Date().getFullYear() + 5)),
|
||||
issuedDate: new Date()
|
||||
} : undefined,
|
||||
officialTitle: formData.officialTitle || undefined,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
createdBy: 'admin'
|
||||
@ -394,6 +396,20 @@ export default function EmployeeForm() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-secondary mb-2">
|
||||
Amtsbezeichnung
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="officialTitle"
|
||||
value={formData.officialTitle}
|
||||
onChange={handleChange}
|
||||
className="input-field"
|
||||
placeholder="z. B. KOK, KHK, EKHK"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-secondary mb-2">
|
||||
Abteilung *
|
||||
|
||||
@ -16,12 +16,23 @@ export default function MyProfile() {
|
||||
const [error, setError] = useState('')
|
||||
const [success, setSuccess] = useState('')
|
||||
|
||||
const [form, setForm] = useState<any | null>(null)
|
||||
const [catalog, setCatalog] = useState<{ id: string; name: string; subcategories: { id: string; name: string; skills: { id: string; name: string }[] }[] }[]>([])
|
||||
const [skills, setSkills] = useState<SkillSelection[]>([])
|
||||
const [activeTab, setActiveTab] = useState<'profile' | 'deputies'>('profile')
|
||||
const [currentUnitId, setCurrentUnitId] = useState<string | null>(null)
|
||||
const [myUnits, setMyUnits] = useState<any[]>([])
|
||||
const [form, setForm] = useState<any | null>(null)
|
||||
const [catalog, setCatalog] = useState<{ id: string; name: string; subcategories: { id: string; name: string; skills: { id: string; name: string }[] }[] }[]>([])
|
||||
const [skills, setSkills] = useState<SkillSelection[]>([])
|
||||
const [activeTab, setActiveTab] = useState<'profile' | 'deputies'>('profile')
|
||||
const [currentUnitId, setCurrentUnitId] = useState<string | null>(null)
|
||||
const [myUnits, setMyUnits] = useState<any[]>([])
|
||||
const AVAILABILITY_OPTIONS = [
|
||||
{ value: 'available', label: 'Verfügbar' },
|
||||
{ value: 'busy', label: 'Beschäftigt' },
|
||||
{ value: 'away', label: 'Abwesend' },
|
||||
{ value: 'vacation', label: 'Urlaub' },
|
||||
{ value: 'sick', label: 'Erkrankt' },
|
||||
{ value: 'training', label: 'Fortbildung' },
|
||||
{ value: 'operation', label: 'Im Einsatz' },
|
||||
{ value: 'parttime', label: 'Teilzeit' },
|
||||
{ value: 'unavailable', label: 'Nicht verfügbar' }
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
if (!employeeId) {
|
||||
@ -143,6 +154,7 @@ export default function MyProfile() {
|
||||
firstName: form.firstName,
|
||||
lastName: form.lastName,
|
||||
position: form.position || 'Teammitglied',
|
||||
officialTitle: form.officialTitle || null,
|
||||
department: form.department || '',
|
||||
employeeNumber: form.employeeNumber || undefined,
|
||||
email: user?.email || form.email,
|
||||
@ -241,8 +253,23 @@ export default function MyProfile() {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-body font-medium text-secondary mb-2">Position</label>
|
||||
<input className="input-field w-full" value={form.position || ''} onChange={(e) => setForm((p: any) => ({ ...p, position: e.target.value }))} placeholder="z. B. Sachbearbeiter; Führungskraft g. D.; Führungskraft h. D." />
|
||||
<p className="text-small text-tertiary mt-1">Beispiele: Sachbearbeiter, Führungskraft g. D., Führungskraft h. D.</p>
|
||||
<input
|
||||
className="input-field w-full"
|
||||
value={form.position || ''}
|
||||
onChange={(e) => setForm((p: any) => ({ ...p, position: e.target.value }))}
|
||||
placeholder="z. B. Sachbearbeitung, Teamleitung"
|
||||
/>
|
||||
<p className="text-small text-tertiary mt-1">Beispiele: Sachbearbeitung, Teamleitung, Stabsstelle.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-body font-medium text-secondary mb-2">Amtsbezeichnung</label>
|
||||
<input
|
||||
className="input-field w-full"
|
||||
value={form.officialTitle || ''}
|
||||
onChange={(e) => setForm((p: any) => ({ ...p, officialTitle: e.target.value }))}
|
||||
placeholder="z. B. KOK, KHK, EKHK"
|
||||
/>
|
||||
<p className="text-small text-tertiary mt-1">Freifeld für Amts- bzw. Dienstbezeichnungen (z. B. KOK, RBe, EKHK).</p>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-body font-medium text-secondary mb-2">NW-Kennung</label>
|
||||
@ -273,6 +300,19 @@ export default function MyProfile() {
|
||||
<input className="input-field w-full" value={form.office || ''} onChange={(e) => setForm((p: any) => ({ ...p, office: e.target.value }))} placeholder="z. B. Gebäude A, 3.OG, Raum 3.12" />
|
||||
<p className="text-small text-tertiary mt-1">Angabe zum Standort, z. B. Gebäude, Etage und Raum.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-body font-medium text-secondary mb-2">Verfügbarkeit</label>
|
||||
<select
|
||||
className="input-field w-full"
|
||||
value={form.availability || 'available'}
|
||||
onChange={(e) => setForm((p: any) => ({ ...p, availability: e.target.value }))}
|
||||
>
|
||||
{AVAILABILITY_OPTIONS.map(option => (
|
||||
<option key={option.value} value={option.value}>{option.label}</option>
|
||||
))}
|
||||
</select>
|
||||
<p className="text-small text-tertiary mt-1">Dieser Status wird in der Mitarbeitendenübersicht und Teamplanung angezeigt.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -567,6 +567,7 @@ export default function SkillSearch() {
|
||||
</div>
|
||||
<div className="text-xs text-tertiary">
|
||||
{employee.position}
|
||||
{employee.officialTitle ? ` • ${employee.officialTitle}` : ''}
|
||||
</div>
|
||||
</div>
|
||||
{selectedSkills.size > 0 && (
|
||||
|
||||
@ -688,7 +688,9 @@ export default function TeamZusammenstellung() {
|
||||
{employee.firstName} {employee.lastName}
|
||||
</div>
|
||||
<div className="text-sm text-tertiary">
|
||||
{employee.position} • {employee.department}
|
||||
{employee.position}
|
||||
{employee.officialTitle ? ` • ${employee.officialTitle}` : ''}
|
||||
{` • ${employee.department}`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
1
shared/index.d.ts
vendored
1
shared/index.d.ts
vendored
@ -46,6 +46,7 @@ export interface Employee {
|
||||
employeeNumber: string
|
||||
photo?: string | null
|
||||
position: string
|
||||
officialTitle?: string | null
|
||||
department: string
|
||||
email?: string | null
|
||||
phone?: string | null
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren