Lots of improvements and changes
Some checks failed
Build and Deploy / Deploy Web (push) Has been cancelled
Build and Deploy / Deploy Discord Bot (push) Has been cancelled

This commit is contained in:
2023-05-27 12:02:33 +02:00
parent 98d73ea593
commit 8121b9b975
21 changed files with 3147 additions and 1599 deletions

14
web/pages/mod/server.vue Normal file
View File

@@ -0,0 +1,14 @@
<template>
<div class="mt-5">
Server Control
</div>
</template>
<script setup>
definePageMeta({
middleware: ["auth"],
moderator: true
})
useHead({ title: 'Server Control | Polarcraft' })
</script>

77
web/pages/mod/users.vue Normal file
View File

@@ -0,0 +1,77 @@
<template>
<div class="mt-5">
<Modal v-if="actionModal.open" :title="actionModal.title">
WIP
</Modal>
<h1 class="text-2xl font-bold text-primary">
Users
</h1>
<div class="mx-auto my-10 max-w-4xl">
<h2 class="mb-2 text-xl font-bold text-primary">User Actions</h2>
<div class="w-full rounded border-[1px] border-primary px-3 py-1 text-left">
<table class="w-full table-auto divide-y divide-neutral-500 rounded">
<tr class="border-b-2 border-primary text-gray-200">
<th class="py-1">Username</th>
<th class="py-1">Team</th>
<th class="py-1">MC Linked</th>
<th class="py-1">Actions</th>
</tr>
<tr v-for="user in users" :key="user._id" class="text-gray-200">
<td class="py-1">{{ user.username }}</td>
<td class="py-1">{{ user.team ? teams.filter(a => a._id === user.team.id)[0].name : '-' }}</td>
<td class="py-1">{{ user.minecraft.uuid ? 'True ' : 'False' }}</td>
<td class="space-x-2 py-1">
<span v-if="currentUser.role.admin" class="rounded bg-red-700 px-2 text-red-300 hover:cursor-pointer hover:bg-red-800" @click="openModal(user, 'ban', ban(user))">Ban</span>
<span class="rounded bg-orange-700 px-2 text-orange-300 hover:cursor-pointer hover:bg-orange-800">Suspend</span>
<span class="rounded bg-yellow-700 px-2 text-yellow-300 hover:cursor-pointer hover:bg-yellow-800">Warn</span>
</td>
</tr>
</table>
</div>
</div>
</div>
</template>
<script setup>
definePageMeta({
middleware: ["auth"],
moderator: true
})
useHead({ title: 'Users | Polarcraft' })
const currentUser = useState('user')
const { data: users } = useFetch('/api/auth/getusers')
const { data: teams } = useFetch('/api/team/all')
const actionModal = ref({
open: false,
title: '',
userId: '',
func: null,
})
const openModal = (user, type, func) => {
if (type === 'ban') actionModal.value.title = 'Ban User'
if (type === 'suspend') actionModal.value.title = 'Suspend User'
if (type === 'warn') actionModal.value.title = 'Warn User'
actionModal.value.func = func
actionModal.value.userId = user._id;
actionModal.value.open = true
}
const ban = async (user) => {
try {
const response = await $fetch(`/api/auth/user/${user._id}/ban`, {
reason: "reason"
})
user = response;
} catch (e) {
console.log(e);
useToast().error('Error banning user')
}
}
</script>

View File

@@ -1,6 +1,59 @@
<template>
<div class="mt-5 text-primary">
Player Store
<Modal
v-if="storeModal.open"
title="Create new store"
:delete="!storeModal.new"
@submit="submitModal"
@delete="deleteStore"
@close="storeModal.open = false"
>
<Input v-model="storeModal.name" background-class="bg-neutral-800">Store name</Input>
<div class="flex gap-x-5">
<Input v-model="storeModal.coords.x" background-class="bg-neutral-800">Coordinate X</Input>
<Input v-model="storeModal.coords.z" background-class="bg-neutral-800">Coordinate Z</Input>
</div>
<h2 class="font-bold">Items</h2>
<div class="max-h-56 space-y-3 overflow-scroll">
<div v-for="item, index in storeModal.items" :key="item.name" class="flex gap-2">
<Input v-model="item.displayName" background-class="bg-neutral-800">Name</Input>
<Input v-model="item.price" background-class="bg-neutral-800">Price per quantity</Input>
<Button type="danger" @click="storeModal.items.splice(index, 1)"><Icon size="1.5em" name="ph:trash" class="-my-2" /></Button>
</div>
</div>
<Button class="" @click="storeModal.items.push({ displayName: '', price: '' })">Add Item</Button>
</Modal>
<h1 class="pb-10 text-2xl font-bold text-primary">
Player Stores
</h1>
<div class="fixed bottom-10 right-10">
<Button class="fixed" @click="openStoreModal(true)">
Create Store
</Button>
</div>
<div class="flex flex-wrap gap-10">
<div v-for="store in stores" :key="store._id.toString()" class="h-min w-96 rounded-lg bg-neutral-800 text-gray-200 shadow relative">
<div v-if="store.ownerId === user._id" class="absolute right-5 top-5 hover:cursor-pointer" @click="openStoreModal(false, store)">
<Icon name="ph:pencil-simple" size="1.6em" />
</div>
<div class="p-5 pb-3">
<div class="flex items-center">
<img :src="'https://api.mineatar.io/face/' + store.owner.minecraft.uuid + '?scale=3'" class="mr-2 aspect-square rounded">
{{ store.owner.username }}
</div>
<h2 class="text-2xl font-bold text-primary">
{{ store.name }}
<span class="text-sm font-medium">({{ store.coords.x }}, {{ store.coords.z }})</span>
</h2>
</div>
<h2 class="ml-3 text-xl font-bold">Items</h2>
<div class="divide-y divide-neutral-600 rounded-lg bg-neutral-700 px-4 pt-2 pb-2">
<div v-for="item in store.items" :key="item.displayname" class="py-1">
<b>{{ item.displayName }}</b> for <b>{{ item.price }}</b>
</div>
</div>
</div>
</div>
</div>
</template>
@@ -9,5 +62,97 @@ definePageMeta({
middleware: ["auth"]
})
const user = useState('user')
useHead({ title: 'Player Stores | Polarcraft' })
const { data: stores } = await useFetch('/api/store');
const storeModal = ref({
open: false,
name: '',
new: false,
id: '',
coords: {
x: '',
z: '',
},
items: [
{ displayName: '', price: '' }
],
})
const openStoreModal = (newStore, store) => {
storeModal.value.open = true;
if (newStore === true) {
storeModal.value.name = '';
storeModal.value.items = [
{ displayName: '', price: '' }
];
storeModal.value.coords = { x: '', z: '' }
storeModal.value.new = true
} else {
storeModal.value.new = false
storeModal.value.items = []
store.items.forEach(item => {
storeModal.value.items.push(item);
})
storeModal.value.name = store.name
storeModal.value.id = store._id
storeModal.value.coords.x = store.coords.x
storeModal.value.coords.z = store.coords.z
}
}
const submitModal = async () => {
try {
const store = await $fetch('/api/store', {
method: 'POST',
body: { name: storeModal.value.name, coords: storeModal.value.coords, items: storeModal.value.items, id: storeModal.value.id || null }
})
if (storeModal.value.id) {
const oldStore = stores.value.filter(a => a._id === storeModal.value.id)[0]
oldStore.name = storeModal.value.name;
oldStore.coords = storeModal.value.coords;
oldStore.items = storeModal.value.items;
} else {
store.owner = user
stores.value.push(store)
}
storeModal.value.open = false
useToast().success('Succesvol store aangemaakt')
} catch (e) {
console.log(e)
useToast().error(e.statusMessage)
}
}
const deleteStore = async () => {
try {
await $fetch('/api/store', {
method: 'DELETE',
body: { id: storeModal.value.id }
})
stores.value = stores.value.filter(a => a._id !== storeModal.value.id)
storeModal.value.open = false
useToast().success('Succesvol store verwijderd')
} catch (e) {
console.log(e)
useToast().error(e.statusMessage)
}
}
</script>