diff --git a/backend/controllers/adminController.js b/backend/controllers/adminController.js index 54b65b4..e09293b 100644 --- a/backend/controllers/adminController.js +++ b/backend/controllers/adminController.js @@ -41,4 +41,14 @@ export const changeTranslation = async (req, res) => { } catch(error) { res.status(403).json({ error: error.message }); } +} + +export const getOpenContacts = async (req, res) => { + try { + const { userid: userId } = req.headers; + const openContacts = await AdminService.getOpenContacts(userId); + res.status(200).json(openContacts); + } catch (error) { + res.status(403).json({ error: error.message }); + } } \ No newline at end of file diff --git a/backend/models/service/contactmessage.js b/backend/models/service/contactmessage.js index f2adae1..0d98636 100644 --- a/backend/models/service/contactmessage.js +++ b/backend/models/service/contactmessage.js @@ -55,6 +55,11 @@ const ContactMessage = sequelize.define('contact_message', { type: DataTypes.BOOLEAN, allowNull: false }, + isFinished: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + } }, { tableName: 'contact_message', timestamps: true, diff --git a/backend/routers/adminRouter.js b/backend/routers/adminRouter.js index a8abef8..f909b27 100644 --- a/backend/routers/adminRouter.js +++ b/backend/routers/adminRouter.js @@ -1,6 +1,6 @@ import { Router } from 'express'; import { authenticate } from '../middleware/authMiddleware.js'; -import { getOpenInterests, changeInterest, deleteInterest, changeTranslation } from '../controllers/adminController.js'; +import { getOpenInterests, changeInterest, deleteInterest, changeTranslation, getOpenContacts } from '../controllers/adminController.js'; const router = Router(); @@ -9,4 +9,6 @@ router.post('/interest', authenticate, changeInterest); router.post('/interest/translation', authenticate, changeTranslation); router.delete('/interest/:id', authenticate, deleteInterest); +router.get('/opencontacts', authenticate, getOpenContacts); + export default router; \ No newline at end of file diff --git a/backend/services/adminService.js b/backend/services/adminService.js index ab9e30f..6467b22 100644 --- a/backend/services/adminService.js +++ b/backend/services/adminService.js @@ -4,13 +4,11 @@ import InterestType from "../models/type/interest.js" import InterestTranslationType from "../models/type/interest_translation.js" import User from "../models/community/user.js"; import UserParamValue from "../models/type/user_param_value.js"; +import ContactMessage from "../models/service/contactmessage.js"; class AdminService { async hasUserAccess(userId, section) { const userRights = await UserRight.findAll({ -/* where: { - userId: userId, - },*/ include: [{ model: UserRightType, as: 'rightType', @@ -119,6 +117,18 @@ class AdminService { } } } + + async getOpenContacts(userId) { + if (!this.hasUserAccess(userId, 'contacts')) { + throw new Error('noaccess'); + } + const openContacts = await ContactMessage.findAll({ + where: { + isFinished: false, + } + }) + return openContacts; + } } export default new AdminService(); \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 85ae096..15113ac 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "axios": "^1.7.2", + "date-fns": "^3.6.0", "dotenv": "^16.4.5", "vue": "~3.4.31", "vue-i18n": "^10.0.0-beta.2", @@ -2513,6 +2514,15 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 6d97449..79a58c1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "axios": "^1.7.2", + "date-fns": "^3.6.0", "dotenv": "^16.4.5", "vue": "~3.4.31", "vue-i18n": "^10.0.0-beta.2", diff --git a/frontend/public/images/icons/cam.png b/frontend/public/images/icons/cam.png new file mode 100644 index 0000000..bbf3a61 Binary files /dev/null and b/frontend/public/images/icons/cam.png differ diff --git a/frontend/public/images/icons/message.png b/frontend/public/images/icons/message.png new file mode 100644 index 0000000..aad72fb Binary files /dev/null and b/frontend/public/images/icons/message.png differ diff --git a/frontend/public/images/icons/message16.png b/frontend/public/images/icons/message16.png index df9a555..25621f7 100644 Binary files a/frontend/public/images/icons/message16.png and b/frontend/public/images/icons/message16.png differ diff --git a/frontend/public/images/icons/message24.png b/frontend/public/images/icons/message24.png index e809fe8..63c7592 100644 Binary files a/frontend/public/images/icons/message24.png and b/frontend/public/images/icons/message24.png differ diff --git a/frontend/public/images/icons/minigames.png b/frontend/public/images/icons/minigames.png new file mode 100644 index 0000000..3f372d5 Binary files /dev/null and b/frontend/public/images/icons/minigames.png differ diff --git a/frontend/public/images/icons/minigames16.png b/frontend/public/images/icons/minigames16.png index c6acb37..6712f98 100644 Binary files a/frontend/public/images/icons/minigames16.png and b/frontend/public/images/icons/minigames16.png differ diff --git a/frontend/public/images/icons/minigames24.png b/frontend/public/images/icons/minigames24.png index fdcdc1f..6b7defc 100644 Binary files a/frontend/public/images/icons/minigames24.png and b/frontend/public/images/icons/minigames24.png differ diff --git a/frontend/public/images/icons/privacy.png b/frontend/public/images/icons/privacy.png index 3fb47f2..45a1abe 100644 Binary files a/frontend/public/images/icons/privacy.png and b/frontend/public/images/icons/privacy.png differ diff --git a/frontend/public/images/icons/privacy16.png b/frontend/public/images/icons/privacy16.png index 4073521..02e6309 100644 Binary files a/frontend/public/images/icons/privacy16.png and b/frontend/public/images/icons/privacy16.png differ diff --git a/frontend/public/images/icons/privacy24.png b/frontend/public/images/icons/privacy24.png index b84e322..f00a972 100644 Binary files a/frontend/public/images/icons/privacy24.png and b/frontend/public/images/icons/privacy24.png differ diff --git a/frontend/src/i18n/locales/de/admin.json b/frontend/src/i18n/locales/de/admin.json index 2126808..54d809b 100644 --- a/frontend/src/i18n/locales/de/admin.json +++ b/frontend/src/i18n/locales/de/admin.json @@ -11,6 +11,14 @@ "isadult": "Nur für Erwachsene", "delete": "Löschen" } + }, + "contacts": { + "title": "[Admin] - Kontaktanfragen", + "date": "Datum", + "from": "Absender", + "actions": "Aktionen", + "open": "Bearbeiten", + "finished": "Abschließen" } } } \ No newline at end of file diff --git a/frontend/src/i18n/locales/de/general.json b/frontend/src/i18n/locales/de/general.json index 4736e7f..925a5a0 100644 --- a/frontend/src/i18n/locales/de/general.json +++ b/frontend/src/i18n/locales/de/general.json @@ -24,5 +24,8 @@ "acceptdatasave": "Ich stimme der vorübergehenden Speicherung meiner Email-Adresse zu.", "accept2": "Ohne diese Zustimmung können wir Dir leider nicht antworten." } + }, + "general": { + "datetimelong": "dd.MM.yyyy HH:mm:ss" } } \ No newline at end of file diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 02cfbd3..bf162ca 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -8,6 +8,7 @@ import SexualitySettingsView from '../views/settings/SexualityView.vue'; import AccountSettingsView from '../views/settings/AccountView.vue'; import InterestsView from '../views/settings/InterestsView.vue'; import AdminInterestsView from '../views/admin/InterestsView.vue'; +import AdminContactsView from '../views/admin/ContactsView.vue'; const routes = [ { @@ -55,7 +56,13 @@ const routes = [ name: 'AdminInterests', component: AdminInterestsView, meta: { requiresAuth: true } - } + }, + { + path: '/admin/contacts', + name: 'AdminContacts', + component: AdminContactsView, + meta: { requiresAuth: true } + }, ]; diff --git a/frontend/src/utils/datetime.js b/frontend/src/utils/datetime.js new file mode 100644 index 0000000..146c1ac --- /dev/null +++ b/frontend/src/utils/datetime.js @@ -0,0 +1,9 @@ +import { format } from 'date-fns'; +import { useI18n } from 'vue-i18n'; + +export function formatDateTimeLong(timestamp) { + const { t } = useI18n(); + const dateFormat = t('general.datetimelong', 'yyyy-MM-dd HH:mm:ss'); + const date = new Date(timestamp); + return format(date, dateFormat); +} diff --git a/frontend/src/views/admin/ContactsView.vue b/frontend/src/views/admin/ContactsView.vue new file mode 100644 index 0000000..049b9c9 --- /dev/null +++ b/frontend/src/views/admin/ContactsView.vue @@ -0,0 +1,64 @@ + + + \ No newline at end of file