1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-08-04 09:59:09 +02:00
parent 05be118a84
commit 2f2d0b1103
3 changed files with 60 additions and 142 deletions

View file

@ -425,10 +425,17 @@ openRevokeLicenseMenu = function(targetId, targetName, licenses)
lib.showContext('revoke_license') lib.showContext('revoke_license')
end end
-- Manual License Entry Menu -- Manual License Entry Menu (Vollständig manuell)
openManualLicenseEntry = function(targetId, targetName) openManualLicenseEntry = function(targetId, targetName)
debugPrint("Öffne manuelle Lizenz-Eingabe für: " .. targetName) debugPrint("Öffne manuelle Lizenz-Eingabe für: " .. targetName)
-- Aktuelles Datum für Standardwerte
local currentDate = os.date("%d.%m.%Y")
-- Berechne Standardablaufdatum (1 Jahr später)
local day, month, year = currentDate:match("(%d+)%.(%d+)%.(%d+)")
local defaultExpireDate = day .. "." .. month .. "." .. (tonumber(year) + 1)
local input = lib.inputDialog('Lizenz manuell ausstellen', { local input = lib.inputDialog('Lizenz manuell ausstellen', {
{type = 'select', label = 'Lizenztyp', options = getLicenseTypeOptions()}, {type = 'select', label = 'Lizenztyp', options = getLicenseTypeOptions()},
{type = 'input', label = 'Name', default = targetName}, {type = 'input', label = 'Name', default = targetName},
@ -438,30 +445,44 @@ openManualLicenseEntry = function(targetId, targetName)
{value = 'female', label = 'Weiblich'}, {value = 'female', label = 'Weiblich'},
{value = 'other', label = 'Divers'} {value = 'other', label = 'Divers'}
}}, }},
{type = 'date', label = 'Ausstellungsdatum', default = os.date("%Y-%m-%d")}, {type = 'input', label = 'Ausstellungsdatum', description = 'Format: DD.MM.YYYY', default = currentDate},
{type = 'date', label = 'Ablaufdatum', default = os.date("%Y-%m-%d", os.time() + 365*24*60*60)}, {type = 'input', label = 'Ablaufdatum', description = 'Format: DD.MM.YYYY', default = defaultExpireDate},
{type = 'input', label = 'Klassen (kommagetrennt)', description = 'z.B. A,B,C', default = ''},
{type = 'input', label = 'Bemerkungen', default = ''},
{type = 'checkbox', label = 'Foto aufnehmen?'} {type = 'checkbox', label = 'Foto aufnehmen?'}
}) })
if not input then return end if not input then return end
local licenseType = input[1] local licenseType = input[1]
-- Klassen verarbeiten
local classes = {}
if input[7] and input[7] ~= "" then
for class in string.gmatch(input[7], '([^,]+)') do
table.insert(classes, class:match("^%s*(.-)%s*$")) -- Leerzeichen entfernen
end
end
local licenseData = { local licenseData = {
name = input[2], name = input[2],
birthday = input[3], birthday = input[3],
gender = input[4], gender = input[4],
issue_date = os.date("%d.%m.%Y", os.time(os.date("!*t", input[5] / 1000))), issue_date = input[5],
expire_date = os.date("%d.%m.%Y", os.time(os.date("!*t", input[6] / 1000))), expire_date = input[6],
classes = classes,
notes = input[8],
license_type = licenseType license_type = licenseType
} }
if input[7] then -- Take photo if input[9] then -- Foto aufnehmen
TriggerEvent('license-system:client:openCamera', targetId, licenseData) TriggerEvent('license-system:client:openCamera', targetId, licenseData)
else else
TriggerServerEvent('license-system:server:issueManualLicense', targetId, licenseData) TriggerServerEvent('license-system:server:issueManualLicense', targetId, licenseData)
end end
end end
-- License Reactivation Menu -- License Reactivation Menu
openReactivateLicenseMenu = function(targetId, targetName) openReactivateLicenseMenu = function(targetId, targetName)
debugPrint("Öffne Lizenz-Reaktivierungs-Menü für: " .. targetName) debugPrint("Öffne Lizenz-Reaktivierungs-Menü für: " .. targetName)

View file

@ -19,7 +19,7 @@ window.addEventListener('message', function(event) {
} }
}); });
// Lizenz anzeigen // In der showLicense Funktion in script.js
function showLicense(data) { function showLicense(data) {
currentLicense = data; currentLicense = data;
const container = document.getElementById('license-container'); const container = document.getElementById('license-container');
@ -69,121 +69,10 @@ function showLicense(data) {
// Notification // Notification
showNotification('Lizenz geladen', 'success'); showNotification('Lizenz geladen', 'success');
}, 500); }, 500);
} }
// Spieler-Foto anzeigen // Erweitere die prepareBackSide Funktion um Bemerkungen anzuzeigen
function displayPlayerPhoto(license) {
const photoImg = document.getElementById('player-photo');
const photoPlaceholder = document.getElementById('photo-placeholder');
if (license.photo_url && license.photo_url !== '') {
photoImg.src = license.photo_url;
photoImg.onload = function() {
photoImg.classList.remove('hidden');
photoPlaceholder.classList.add('hidden');
};
photoImg.onerror = function() {
photoImg.classList.add('hidden');
photoPlaceholder.classList.remove('hidden');
};
} else {
photoImg.classList.add('hidden');
photoPlaceholder.classList.remove('hidden');
}
}
// Lizenz-Klassen anzeigen
function displayLicenseClasses(license) {
const classesRow = document.getElementById('license-classes-row');
const classesElement = document.getElementById('license-classes');
if (license.license_type === 'drivers_license' && license.classes && license.classes !== '[]') {
try {
const classes = JSON.parse(license.classes);
if (classes && classes.length > 0) {
classesElement.textContent = classes.join(', ');
classesRow.style.display = 'flex';
return;
}
} catch (e) {
console.error('Fehler beim Parsen der Klassen:', e);
}
}
classesRow.style.display = 'none';
}
// Lizenz-Status anzeigen
function displayLicenseStatus(license) {
const statusElement = document.getElementById('license-status');
const statusIcon = statusElement.querySelector('.status-icon');
const statusText = statusElement.querySelector('.status-text');
// Ablaufdatum prüfen
let isExpired = false;
let isExpiringSoon = false;
if (license.expire_date) {
const expireDate = new Date(license.expire_date);
const today = new Date();
const daysUntilExpire = Math.ceil((expireDate - today) / (1000 * 60 * 60 * 24));
isExpired = daysUntilExpire < 0;
isExpiringSoon = daysUntilExpire <= 30 && daysUntilExpire >= 0;
}
// Status setzen
if (!license.is_active || isExpired) {
statusElement.className = 'license-status inactive';
statusIcon.className = 'status-icon fas fa-times-circle';
statusText.textContent = isExpired ? 'Abgelaufen' : 'Ungültig';
} else if (isExpiringSoon) {
statusElement.className = 'license-status warning';
statusIcon.className = 'status-icon fas fa-exclamation-triangle';
statusText.textContent = 'Läuft bald ab';
} else {
statusElement.className = 'license-status active';
statusIcon.className = 'status-icon fas fa-check-circle';
statusText.textContent = 'Gültig';
}
}
// Gültigkeits-Indikator anzeigen
function displayValidityIndicator(license) {
const validityFill = document.getElementById('validity-fill');
const validityText = document.getElementById('validity-text');
if (!license.expire_date) {
validityText.textContent = 'Unbegrenzt gültig';
validityFill.style.width = '100%';
validityFill.style.backgroundColor = '#4CAF50';
return;
}
const issueDate = new Date(license.issue_date);
const expireDate = new Date(license.expire_date);
const today = new Date();
const totalDays = Math.ceil((expireDate - issueDate) / (1000 * 60 * 60 * 24));
const remainingDays = Math.ceil((expireDate - today) / (1000 * 60 * 60 * 24));
const percentage = Math.max(0, Math.min(100, (remainingDays / totalDays) * 100));
validityFill.style.width = percentage + '%';
if (remainingDays < 0) {
validityText.textContent = 'Abgelaufen';
validityFill.style.backgroundColor = '#f44336';
} else if (remainingDays <= 30) {
validityText.textContent = `Noch ${remainingDays} Tage gültig`;
validityFill.style.backgroundColor = '#ff9800';
} else {
validityText.textContent = `Noch ${remainingDays} Tage gültig`;
validityFill.style.backgroundColor = '#4CAF50';
}
}
// Rückseite vorbereiten
function prepareBackSide(license) { function prepareBackSide(license) {
const classesGrid = document.getElementById('classes-grid'); const classesGrid = document.getElementById('classes-grid');
const restrictionsList = document.getElementById('restrictions-list'); const restrictionsList = document.getElementById('restrictions-list');
@ -192,7 +81,7 @@ function prepareBackSide(license) {
// Klassen-Grid für Führerschein // Klassen-Grid für Führerschein
if (license.license_type === 'drivers_license' && license.classes) { if (license.license_type === 'drivers_license' && license.classes) {
try { try {
const classes = JSON.parse(license.classes); const classes = Array.isArray(license.classes) ? license.classes : JSON.parse(license.classes);
classesGrid.innerHTML = ''; classesGrid.innerHTML = '';
const classDescriptions = { const classDescriptions = {
@ -207,15 +96,19 @@ function prepareBackSide(license) {
'DE': 'Bus mit Anhänger' 'DE': 'Bus mit Anhänger'
}; };
classes.forEach(cls => { if (classes && classes.length > 0) {
const classItem = document.createElement('div'); classes.forEach(cls => {
classItem.className = 'class-item'; const classItem = document.createElement('div');
classItem.innerHTML = ` classItem.className = 'class-item';
<div class="class-letter">${cls}</div> classItem.innerHTML = `
<div class="class-description">${classDescriptions[cls] || 'Unbekannt'}</div> <div class="class-letter">${cls}</div>
`; <div class="class-description">${classDescriptions[cls] || 'Unbekannt'}</div>
classesGrid.appendChild(classItem); `;
}); classesGrid.appendChild(classItem);
});
} else {
classesGrid.innerHTML = '<p>Keine Klassen verfügbar</p>';
}
} catch (e) { } catch (e) {
classesGrid.innerHTML = '<p>Keine Klassen verfügbar</p>'; classesGrid.innerHTML = '<p>Keine Klassen verfügbar</p>';
} }
@ -230,6 +123,7 @@ function prepareBackSide(license) {
notesText.textContent = license.notes || 'Keine besonderen Bemerkungen'; notesText.textContent = license.notes || 'Keine besonderen Bemerkungen';
} }
// Karte drehen // Karte drehen
function flipCard() { function flipCard() {
const frontSide = document.querySelector('.license-content, .license-footer'); const frontSide = document.querySelector('.license-content, .license-footer');

View file

@ -805,7 +805,7 @@ RegisterNetEvent('license-system:server:reactivateLicense', function(targetId, l
end end
end) end)
-- EVENT HANDLER: Manuelle Lizenz ausstellen -- EVENT HANDLER: Manuelle Lizenz ausstellen (Erweitert)
RegisterNetEvent('license-system:server:issueManualLicense', function(targetId, licenseData) RegisterNetEvent('license-system:server:issueManualLicense', function(targetId, licenseData)
local src = source local src = source
debugPrint("=== Event: issueManualLicense ===") debugPrint("=== Event: issueManualLicense ===")
@ -833,29 +833,29 @@ RegisterNetEvent('license-system:server:issueManualLicense', function(targetId,
local targetCitizenId = targetPlayer.PlayerData.citizenid local targetCitizenId = targetPlayer.PlayerData.citizenid
local issuerCitizenId = issuerPlayer.PlayerData.citizenid local issuerCitizenId = issuerPlayer.PlayerData.citizenid
-- Check if license type is valid -- Prüfen ob Lizenztyp gültig ist
if not Config.LicenseTypes[licenseData.license_type] then if not Config.LicenseTypes[licenseData.license_type] then
TriggerClientEvent('QBCore:Notify', src, 'Ungültiger Lizenztyp!', 'error') TriggerClientEvent('QBCore:Notify', src, 'Ungültiger Lizenztyp!', 'error')
return return
end end
-- Save photo if provided -- Foto speichern falls vorhanden
if licenseData.photo_url then if licenseData.photo_url then
-- Here you would save the photo to your storage system
-- For example, to a folder or database
-- This is just a placeholder
debugPrint("Foto für Lizenz vorhanden") debugPrint("Foto für Lizenz vorhanden")
end end
-- First deactivate any existing licenses of this type -- Alte Lizenzen deaktivieren
local deactivateQuery = "UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ?" local deactivateQuery = "UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ?"
MySQL.query.await(deactivateQuery, {targetCitizenId, licenseData.license_type}) MySQL.query.await(deactivateQuery, {targetCitizenId, licenseData.license_type})
-- Insert into database with manual data -- Klassen zu JSON konvertieren
local classesJson = json.encode(licenseData.classes or {})
-- In Datenbank einfügen mit manuellen Daten
local query = [[ local query = [[
INSERT INTO player_licenses INSERT INTO player_licenses
(citizenid, license_type, name, birthday, gender, issue_date, expire_date, issued_by, is_active, photo_url, created_at) (citizenid, license_type, name, birthday, gender, issue_date, expire_date, issued_by, is_active, classes, photo_url, notes, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?)
]] ]]
local createdAt = os.time() local createdAt = os.time()
@ -869,25 +869,27 @@ RegisterNetEvent('license-system:server:issueManualLicense', function(targetId,
licenseData.issue_date, licenseData.issue_date,
licenseData.expire_date, licenseData.expire_date,
issuerCitizenId, issuerCitizenId,
classesJson,
licenseData.photo_url or '', licenseData.photo_url or '',
licenseData.notes or '',
createdAt createdAt
} }
local result = MySQL.insert.await(query, insertData) local result = MySQL.insert.await(query, insertData)
if result then if result then
-- Invalidate cache -- Cache invalidieren
invalidateCache(targetCitizenId) invalidateCache(targetCitizenId)
local targetName = getPlayerName(targetId) local targetName = getPlayerName(targetId)
local issuerName = getPlayerName(src) local issuerName = getPlayerName(src)
local config = Config.LicenseTypes[licenseData.license_type] local config = Config.LicenseTypes[licenseData.license_type]
-- Notifications -- Benachrichtigungen
TriggerClientEvent('QBCore:Notify', src, 'Lizenz erfolgreich ausgestellt für ' .. targetName, 'success') TriggerClientEvent('QBCore:Notify', src, 'Lizenz erfolgreich ausgestellt für ' .. targetName, 'success')
TriggerClientEvent('QBCore:Notify', targetId, 'Du hast eine neue Lizenz erhalten: ' .. config.label, 'success') TriggerClientEvent('QBCore:Notify', targetId, 'Du hast eine neue Lizenz erhalten: ' .. config.label, 'success')
-- Events -- Events senden
TriggerClientEvent('license-system:client:licenseIssued', src, targetId, licenseData.license_type) TriggerClientEvent('license-system:client:licenseIssued', src, targetId, licenseData.license_type)
TriggerClientEvent('license-system:client:refreshMenu', src) TriggerClientEvent('license-system:client:refreshMenu', src)
@ -898,6 +900,7 @@ RegisterNetEvent('license-system:server:issueManualLicense', function(targetId,
end end
end) end)
-- EVENT HANDLER: Alle Lizenzen eines Spielers anfordern (inkl. inaktive) -- EVENT HANDLER: Alle Lizenzen eines Spielers anfordern (inkl. inaktive)
RegisterNetEvent('license-system:server:requestAllPlayerLicenses', function(targetId, includeInactive) RegisterNetEvent('license-system:server:requestAllPlayerLicenses', function(targetId, includeInactive)
local src = source local src = source