feat(match3): Erweiterung der Match3-Admin-Funktionalitäten und -Modelle

- Implementierung neuer Endpunkte für die Verwaltung von Match3-Kampagnen, Levels, Objectives und Tile-Typen im Admin-Bereich.
- Anpassung der Admin-Services zur Unterstützung von Benutzerberechtigungen und Fehlerbehandlung.
- Einführung von neuen Modellen und Assoziationen für Match3-Levels und Tile-Typen in der Datenbank.
- Verbesserung der Internationalisierung für Match3-spezifische Texte in Deutsch und Englisch.
- Aktualisierung der Frontend-Routen und -Komponenten zur Verwaltung von Match3-Inhalten.
This commit is contained in:
Torsten Schulz (local)
2025-08-23 06:00:29 +02:00
parent 3eb7ae4e93
commit e168adeb51
40 changed files with 6474 additions and 1007 deletions

View File

@@ -1,128 +1,212 @@
import match3Service from '../services/match3Service.js';
import Match3Service from '../services/match3Service.js';
class Match3Controller {
/**
* Lädt alle aktiven Kampagnen
*/
async getCampaigns(req, res) {
try {
const campaigns = await match3Service.getActiveCampaigns();
res.json({ success: true, data: campaigns });
} catch (error) {
console.error('Error in getCampaigns:', error);
res.status(500).json({ success: false, message: 'Fehler beim Laden der Kampagnen' });
}
}
/**
* Lädt eine spezifische Kampagne
*/
async getCampaign(req, res) {
try {
const { campaignId } = req.params;
const campaign = await match3Service.getCampaign(campaignId);
if (!campaign) {
return res.status(404).json({ success: false, message: 'Kampagne nicht gefunden' });
}
res.json({ success: true, data: campaign });
} catch (error) {
console.error('Error in getCampaign:', error);
res.status(500).json({ success: false, message: 'Fehler beim Laden der Kampagne' });
}
}
/**
* Lädt den Benutzerfortschritt für eine Kampagne
*/
async getUserProgress(req, res) {
try {
const { campaignId } = req.params;
const userId = req.headers.userid || req.user?.id;
if (!userId) {
return res.status(401).json({ success: false, message: 'Benutzer-ID nicht gefunden' });
}
const userProgress = await match3Service.getUserProgress(userId, campaignId);
res.json({ success: true, data: userProgress });
} catch (error) {
console.error('Error in getUserProgress:', error);
res.status(500).json({ success: false, message: 'Fehler beim Laden des Fortschritts' });
}
}
/**
* Aktualisiert den Level-Fortschritt eines Benutzers
*/
async updateLevelProgress(req, res) {
try {
const { campaignId, levelId } = req.params;
const userId = req.headers.userid || req.user?.id;
const { score, moves, time, stars, isCompleted } = req.body;
if (!userId) {
return res.status(401).json({ success: false, message: 'Benutzer-ID nicht gefunden' });
}
if (!score || !moves || !stars) {
return res.status(400).json({
success: false,
message: 'Alle erforderlichen Felder müssen ausgefüllt werden'
});
}
const levelData = {
score: parseInt(score),
moves: parseInt(moves),
time: time ? parseInt(time) : 0,
stars: parseInt(stars),
isCompleted: Boolean(isCompleted)
};
const result = await match3Service.updateLevelProgress(userId, campaignId, levelId, levelData);
res.json({ success: true, data: result });
} catch (error) {
console.error('Error in updateLevelProgress:', error);
res.status(500).json({ success: false, message: 'Fehler beim Aktualisieren des Fortschritts' });
}
}
/**
* Lädt die Bestenliste für eine Kampagne
*/
async getLeaderboard(req, res) {
try {
const { campaignId } = req.params;
const { limit = 10 } = req.query;
const leaderboard = await match3Service.getLeaderboard(campaignId, parseInt(limit));
res.json({ success: true, data: leaderboard });
} catch (error) {
console.error('Error in getLeaderboard:', error);
res.status(500).json({ success: false, message: 'Fehler beim Laden der Bestenliste' });
}
}
/**
* Lädt Statistiken für einen Benutzer
*/
async getUserStats(req, res) {
try {
const userId = req.headers.userid || req.user?.id;
if (!userId) {
return res.status(401).json({ success: false, message: 'Benutzer-ID nicht gefunden' });
}
const stats = await match3Service.getUserStats(userId);
res.json({ success: true, data: stats });
} catch (error) {
console.error('Error in getUserStats:', error);
res.status(500).json({ success: false, message: 'Fehler beim Laden der Statistiken' });
}
}
function extractHashedUserId(req) {
return req.headers?.userid;
}
export default new Match3Controller();
class Match3Controller {
constructor() {
this.service = Match3Service;
// Binde alle Methoden an die Klasse
this.getCampaigns = this.getCampaigns.bind(this);
this.getCampaign = this.getCampaign.bind(this);
this.getLevel = this.getLevel.bind(this);
this.getUserProgress = this.getUserProgress.bind(this);
this.updateLevelProgress = this.updateLevelProgress.bind(this);
this.getUserStats = this.getUserStats.bind(this);
this.cleanupUserProgress = this.cleanupUserProgress.bind(this);
}
// Kampagnen-Endpunkte
async getCampaigns(req, res) {
try {
const result = await this.service.getCampaigns();
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Error in getCampaigns:', error);
const status = error.status || 500;
const message = error.message || 'Internal server error';
res.status(status).json({
success: false,
message: message
});
}
}
async getCampaign(req, res) {
try {
const result = await this.service.getCampaign(req.params.id);
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Error in getCampaign:', error);
const status = error.status || 500;
const message = error.message || 'Internal server error';
res.status(status).json({
success: false,
message: message
});
}
}
async getLevel(req, res) {
try {
const result = await this.service.getLevel(req.params.id);
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Error in getLevel:', error);
const status = error.status || 500;
const message = error.message || 'Internal server error';
res.status(status).json({
success: false,
message: message
});
}
}
// Benutzer-spezifische Endpunkte
async getUserProgress(req, res) {
try {
const userId = extractHashedUserId(req);
if (!userId) {
return res.status(401).json({
success: false,
message: 'User ID required'
});
}
const result = await this.service.getUserProgress(userId, req.params.campaignId);
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Error in getUserProgress:', error);
const status = error.status || 500;
const message = error.message || 'Internal server error';
res.status(status).json({
success: false,
message: message
});
}
}
async updateLevelProgress(req, res) {
try {
const userId = extractHashedUserId(req);
if (!userId) {
return res.status(401).json({
success: false,
message: 'User ID required'
});
}
const { score, moves, time, stars, securityHash, timestamp } = req.body;
// Prüfe ob alle erforderlichen Sicherheitsdaten vorhanden sind
if (!securityHash || !timestamp) {
return res.status(400).json({
success: false,
message: 'Security validation data missing'
});
}
const result = await this.service.updateLevelProgress(
userId,
req.params.campaignId,
req.params.levelId,
score,
moves,
time,
stars,
securityHash,
timestamp
);
res.status(201).json({
success: true,
data: result
});
} catch (error) {
console.error('Error in updateLevelProgress:', error);
const status = error.status || 500;
const message = error.message || 'Internal server error';
res.status(status).json({
success: false,
message: message
});
}
}
// Bereinige falsche Level-Abschlüsse für einen Benutzer
async cleanupUserProgress(req, res) {
try {
const userId = extractHashedUserId(req);
if (!userId) {
return res.status(401).json({
success: false,
message: 'User ID required'
});
}
const result = await this.service.cleanupUserProgress(userId, req.params.campaignId);
if (result.success) {
res.json({
success: true,
data: result
});
} else {
res.status(400).json({
success: false,
message: result.message
});
}
} catch (error) {
console.error('Error in cleanupUserProgress:', error);
const status = error.status || 500;
const message = error.message || 'Internal server error';
res.status(status).json({
success: false,
message: message
});
}
}
async getUserStats(req, res) {
try {
const userId = extractHashedUserId(req);
if (!userId) {
return res.status(401).json({
success: false,
message: 'User ID required'
});
}
const result = await this.service.getUserStats(userId);
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Error in getUserStats:', error);
const status = error.status || 500;
const message = error.message || 'Internal server error';
res.status(status).json({
success: false,
message: message
});
}
}
}
export default Match3Controller;