Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"eslint-plugin-vue": "^9.32.0",
"knip": "^5.45.0",
"openapi-typescript": "^7.6.1",
"postcss-html": "^1.8.0",
"postcss-preset-env": "^10.1.5",
"prettier": "^3.5.2",
"stylelint": "^16.15.0",
Expand All @@ -53,6 +54,6 @@
"vite-plugin-vuetify": "^2.1.0",
"vite-svg-loader": "^5.1.0",
"vue-tsc": "^2.2.6",
"vuetify": "^3.7.14"
"vuetify": "^3.9.5"
}
}
51 changes: 27 additions & 24 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 11 additions & 24 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,42 +1,29 @@
<script setup lang="ts">
import { useProfileStore } from './store';
import { useProfileStore, useToastStore } from './store';
import { onMounted } from 'vue';

const profileStore = useProfileStore();
const toastStore = useToastStore();

onMounted(() => {
profileStore.fromUrl();
profileStore.setupAdminSession(null);
});
</script>

<template>
<main class="container">
<RouterView />
</main>
<footer>
Made by
<a href="https://app.profcomff.com"><img src="https://app.profcomff.com/favicon.png" class="logo" /></a>
in association with
<a href="https://dyakov.space"><img src="https://dyakov.space/files/Icon.svg" class="logo" /></a>
</footer>
<v-app class="container">
<main class="main">
<Suspense>
<RouterView />
</Suspense>
</main>
<v-snackbar-queue v-model="toastStore.queue"></v-snackbar-queue>
</v-app>
</template>

<style scoped>
.container {
width: 100%;
height: 100%;
}

footer {
position: sticky;
bottom: 0;
width: 100%;
color: gray;
text-align: center;

& .logo {
height: 30px;
vertical-align: middle;
}
}
</style>
34 changes: 34 additions & 0 deletions src/components/achievements/AchievementCreateForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script setup lang="ts">
import { useAchievementStore } from '@/store';
import { ref } from 'vue';

const achievementStore = useAchievementStore();

const name = ref('');
const description = ref('');

async function createAchievement() {
const pic = (document.getElementById('pic') as HTMLFormElement).files[0];
await achievementStore.create(name.value, description.value, pic);
}
</script>

<template>
<form id="form-create" action="submit">
<p>
<label for="name">Название</label>
<input v-model="name" type="text" name="name" id="name" />
</p>
<p>
<label for="description">Описание</label>
<input v-model="description" type="text" name="description" id="description" />
</p>
<p>
<label for="photo">Иконка</label>
<input type="file" name="picture_file" id="pic" />
</p>
<v-btn @click="createAchievement">Создать</v-btn>
</form>
</template>

<style lang="css" scoped></style>
39 changes: 39 additions & 0 deletions src/components/achievements/AchievementDeleteButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script setup lang="ts">
import { router } from '@/router';
import { useAchievementStore } from '@/store';
import { Ref } from 'vue';

const props = defineProps({
id: { type: Number, required: true },
});
const achievementStore = useAchievementStore();

async function confirmDeletion(isActive: Ref<boolean>) {
await achievementStore.deleteAchievement(props.id);

isActive.value = false;
router.push('/achievements');
}

async function dismissDeletion(isActive: Ref<boolean>) {
isActive.value = false;
}
</script>

<template>
<v-dialog>
<template #activator="{ props: activatorProps }">
<v-btn v-bind="activatorProps" color="secondary">Удалить</v-btn>
</template>

<template #default="{ isActive }">
<h1>Удалить {{ id }}?</h1>
<p>
<v-btn @click="dismissDeletion(isActive)">Нет</v-btn>
<v-btn @click="confirmDeletion(isActive)">Да</v-btn>
</p>
</template>
</v-dialog>
</template>

<style lang="css" scoped></style>
32 changes: 32 additions & 0 deletions src/components/achievements/AchievementEditForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script setup lang="ts">
import { useAchievementStore } from '@/store';
import { ref } from 'vue';

defineProps({
id: { type: Number, required: true },
});

const achievementStore = useAchievementStore();

const newName = ref('');
const newDescription = ref('');
</script>

<template>
<form id="achievement-info" @submit.prevent>
<h2>Изменить достижение</h2>

<p>
<label for="name">Название</label>
<input v-model="newName" name="name" id="name" />
</p>

<p>
<label for="description">Описание</label>
<input v-model="newDescription" name="description" id="description" />
</p>
<v-btn @click="achievementStore.edit(id, newName, newDescription)">Изменить</v-btn>
</form>
</template>

<style lang="css" scoped></style>
50 changes: 50 additions & 0 deletions src/components/achievements/AchievementGiveForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script setup lang="ts">
import { useAchievementStore } from '@/store';
import { ref, onMounted, onUpdated } from 'vue';

const props = defineProps<{
definedAchievement?: number;
definedReceiver?: number;
}>();

const achievementId = ref(0);
const receiverId = ref(0);

onMounted(() => {
achievementId.value = props.definedAchievement ?? 0;
receiverId.value = props.definedReceiver ?? 0;
});

onUpdated(() => {
if (props.definedAchievement) {
achievementId.value = props.definedAchievement;
}
if (props.definedReceiver) {
receiverId.value = props.definedReceiver;
}
});

const achievementStore = useAchievementStore();
</script>

<template>
<form action="submit">
<p>
<label for="achievement-id">Номер достижения</label>
<input
v-model="achievementId"
type="number"
name="achievement_id"
id="achievement-id"
:disabled="!!definedAchievement"
/>
</p>
<p>
<label for="user-id">User id</label>
<input v-model="receiverId" type="number" name="user_id" id="user-id" :disabled="!!definedReceiver" />
</p>
<v-btn @click="achievementStore.createReceiver(achievementId, receiverId)">Выдать</v-btn>
</form>
</template>

<style lang="css" scoped></style>
Loading