Files
yourpart3/backend/controllers/navigationController.js
Torsten Schulz (local) bb91c2bbe5 Add NPC creation and titles retrieval functionality in Admin module
- Implemented createNPCs method in AdminController to handle NPC creation with specified parameters including region, age, title, and count.
- Added getTitlesOfNobility method in AdminController to retrieve available titles for users.
- Updated adminRouter to include new routes for creating NPCs and fetching titles.
- Enhanced navigationController and frontend localization files to support new NPC creation feature.
- Introduced corresponding UI components and routes for NPC management in the admin interface.
2026-01-07 16:45:39 +01:00

420 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import User from '../models/community/user.js';
import UserParam from '../models/community/user_param.js';
import UserRight from '../models/community/user_right.js';
import UserRightType from '../models/type/user_right.js';
import UserParamType from '../models/type/user_param.js';
import FalukantUser from '../models/falukant/data/user.js';
import VocabService from '../services/vocabService.js';
const menuStructure = {
home: {
visible: ["all"],
children: {},
path: "/",
icon: "logo_mono.png"
},
friends: {
visible: ["all"],
children: {
manageFriends: {
visible: ["all"],
path: "/friends",
icon: "friends24.png"
}
},
showLoggedinFriends: 1,
icon: "friends24.png"
},
socialnetwork: {
visible: ["all"],
icon: "socialnetwork.png",
children: {
guestbook: {
visible: ["all"],
path: "/socialnetwork/guestbook"
},
blog: {
visible: ["all"],
path: "/blogs"
},
usersearch: {
visible: ["all"],
path: "/socialnetwork/search"
},
forum: {
visible: ["all"],
path: "/socialnetwork/forum",
showForums: 1
},
gallery: {
visible: ["all"],
path: "/socialnetwork/gallery"
},
vocabtrainer: {
visible: ["all"],
path: "/socialnetwork/vocab",
children: {}
},
blockedUsers: {
visible: ["all"],
path: "/socialnetwork/blocked"
},
oneTimeInvitation: {
visible: ["all"],
path: "/socialnetwork/onetimeinvitation"
},
diary: {
visible: ["all"],
path: "/socialnetwork/diary"
},
erotic: {
visible: ["over18"],
children: {
pictures: {
visible: ["over18"],
path: "/socialnetwork/erotic/pictures"
},
videos: {
visible: ["over18"],
path: "/socialnetwork/erotic/videos"
}
}
}
}
},
chats: {
visible: ["over12"],
icon: "chat.png",
children: {
multiChat: {
visible: ["over12"],
action: "openMultiChat",
view: "window",
class: "multiChatDialog",
icon: "multichat24.png"
},
randomChat: {
visible: ["over12"],
action: "openRanomChat",
view: "window",
class: "randomChatDialog"
},
eroticChat: {
visible: ["over18"],
action: "openEroticChat",
view: "window",
class: "eroticChatWindow"
}
}
},
falukant: {
visible: ["all"],
icon: "falukant16.png",
children: {
create: {
visible: ["nofalukantaccount"],
path: "/falukant/create"
},
overview: {
visible: ["hasfalukantaccount"],
path: "/falukant/home"
},
towns: {
visible: ["hasfalukantaccount"],
path: "/falukant/branch"
},
family: {
visible: ["hasfalukantaccount"],
path: "/falukant/family"
},
house: {
visible: ["hasfalukantaccount"],
path: "/falukant/house"
},
nobility: {
visible: ["hasfalukantaccount"],
path: "/falukant/nobility"
},
church: {
visible: ["hasfalukantaccount"],
path: "/falukant/church"
},
politics: {
visible: ["hasfalukantaccount"],
path: "/falukant/politics"
},
education: {
visible: ["hasfalukantaccount"],
path: "/falukant/education"
},
health: {
visible: ["hasfalukantaccount"],
path: "/falukant/health"
},
bank: {
visible: ["hasfalukantaccount"],
path: "/falukant/bank"
},
darknet: {
visible: ["hasfalukantaccount"],
path: "/falukant/darknet"
},
reputation: {
visible: ["hasfalukantaccount"],
path: "/falukant/reputation"
},
moneyhistory: {
visible: ["hasfalukantaccount"],
path: "/falukant/moneyhistory"
}
}
},
minigames: {
visible: ["all"],
icon: "minigames16.png",
children: {
match3: {
visible: ["all"],
path: "/minigames/match3"
},
taxi: {
visible: ["all"],
path: "/minigames/taxi"
}
}
},
settings: {
visible: ["all"],
icon: "settings16.png",
children: {
homepage: {
visible: ["all"],
path: "/settings/homepage"
},
account: {
visible: ["all"],
path: "/settings/account"
},
personal: {
visible: ["all"],
path: "/settings/personal"
},
view: {
visible: ["all"],
path: "/settings/view"
},
interests: {
visible: ["all"],
path: "/settings/interests"
},
flirt: {
visible: ["over14"],
path: "/settings/flirt"
},
sexuality: {
visible: ["over14"],
path: "/settings/sexuality"
},
notifications: {
visible: ["all"],
path: "/settings/notifications"
}
}
},
administration: {
visible: ["anyadmin"],
children: {
contactrequests: {
visible: ["mainadmin", "contactrequests"],
path: "/admin/contacts"
},
users: {
visible: ["mainadmin", "useradministration"],
children: {
userlist: {
visible: ["mainadmin", "useradministration"],
path: "/admin/users"
},
userstatistics: {
visible: ["mainadmin"],
path: "/admin/users/statistics"
},
userrights: {
visible: ["mainadmin", "rights"],
path: "/admin/rights"
}
}
},
forum: {
visible: ["mainadmin", "forum"],
path: "/admin/forum"
},
chatrooms: {
visible: ["mainadmin", "chatrooms"],
path: "/admin/chatrooms"
},
servicesStatus: {
visible: ["mainadmin"],
path: "/admin/services/status"
},
interests: {
visible: ["mainadmin", "interests"],
path: "/admin/interests"
},
falukant: {
visible: ["mainadmin", "falukant"],
children: {
logentries: {
visible: ["mainadmin", "falukant"],
path: "/admin/falukant/logentries"
},
edituser: {
visible: ["mainadmin", "falukant"],
path: "/admin/falukant/edituser"
},
database: {
visible: ["mainadmin", "falukant"],
path: "/admin/falukant/database"
},
mapEditor: {
visible: ["mainadmin", "falukant"],
path: "/admin/falukant/map"
},
createNPC: {
visible: ["mainadmin", "falukant"],
path: "/admin/falukant/create-npc"
},
}
},
minigames: {
visible: ["mainadmin", "match3"],
children: {
match3: {
visible: ["mainadmin", "match3"],
path: "/admin/minigames/match3"
},
taxiTools: {
visible: ["mainadmin", "taxi"],
path: "/admin/minigames/taxi-tools"
}
}
}
}
}
};
class NavigationController {
constructor() {
this.menu = this.menu.bind(this);
this.vocabService = new VocabService();
}
calculateAge(birthDate) {
const today = new Date();
const birthDateObj = new Date(birthDate);
let age = today.getFullYear() - birthDateObj.getFullYear();
const monthDiff = today.getMonth() - birthDateObj.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDateObj.getDate())) {
age--;
}
return age;
}
async filterMenu(menu, rights, age, userId) {
const filteredMenu = {};
try {
const hasFalukantAccount = await this.hasFalukantAccount(userId);
for (const [key, value] of Object.entries(menu)) {
if (value.visible.includes("all")
|| value.visible.some(v => rights.includes(v)) || (value.visible.includes("anyadmin") && rights.length > 0)
|| (value.visible.includes("over14") && age >= 14)
|| (value.visible.includes("over12") && age >= 12)
|| (value.visible.includes("over18") && age >= 18)
|| (value.visible.includes('nofalukantaccount') && !hasFalukantAccount)
|| (value.visible.includes('hasfalukantaccount') && hasFalukantAccount)) {
const { visible, ...itemWithoutVisible } = value;
filteredMenu[key] = { ...itemWithoutVisible };
if (value.children) {
filteredMenu[key].children = await this.filterMenu(value.children, rights, age, userId);
}
}
}
} catch (error) {
console.error('Error filtering menu:', error);
// Return empty menu if filtering fails
return {};
}
return filteredMenu;
}
async menu(req, res) {
try {
const { userid } = req.params;
const user = await User.findOne({ where: { hashedId: userid } });
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
const userRights = await UserRight.findAll({
where: { userId: user.id },
include: [{
model: UserRightType,
as: 'rightType',
required: false
}]
});
const userBirthdateParams = await UserParam.findAll({
where: { userId: user.id },
include: [
{
model: UserParamType,
as: 'paramType',
where: { description: 'birthdate' }
}
]
});
const birthDate = userBirthdateParams.length > 0 ? userBirthdateParams[0].value : (new Date()).toDateString();
const age = this.calculateAge(birthDate);
const rights = userRights.map(ur => ur.rightType?.title).filter(Boolean);
const filteredMenu = await this.filterMenu(menuStructure, rights, age, user.id);
// Dynamisches Submenü: Treffpunkt → Vokabeltrainer → (Neue Sprache + abonnierte/angelegte)
// Wichtig: "Neue Sprache" soll IMMER sichtbar sein auch wenn die DB-Abfrage (noch) fehlschlägt.
if (filteredMenu?.socialnetwork?.children?.vocabtrainer) {
const children = {
newLanguage: { path: '/socialnetwork/vocab/new' },
};
try {
const langs = await this.vocabService.listLanguagesForMenu(user.id);
for (const l of langs) {
children[`lang_${l.id}`] = { path: `/socialnetwork/vocab/${l.id}`, label: l.name };
}
} catch (e) {
console.warn('[menu] Konnte Vokabeltrainer-Sprachen nicht laden:', e?.message || e);
}
filteredMenu.socialnetwork.children.vocabtrainer.children = children;
}
res.status(200).json(filteredMenu);
} catch (error) {
console.error('Error fetching menu:', error);
// Return a minimal working menu instead of 500 error
res.status(200).json({
home: { path: "/", icon: "logo_mono.png" },
settings: { path: "/settings", icon: "settings16.png", children: {} }
});
}
}
async hasFalukantAccount(userId) {
try {
const falukantUser = await FalukantUser.findOne({ where: { userId: userId } });
return falukantUser !== null;
} catch (error) {
console.error('Error checking falukant account:', error);
return false; // Fallback: assume no falukant account if error occurs
}
}
}
export default NavigationController;