убрал пока ненужную модульность, изменил главную страницу, логин и админку
This commit is contained in:
parent
58da850137
commit
c812273f1b
@ -1,9 +1,16 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { QLayout, QHeader, QPageContainer} from 'quasar'
|
||||||
|
const drawer = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<router-view />
|
<q-layout view="lHh Lpr lFf">
|
||||||
</template>
|
<q-header elevated>
|
||||||
|
</q-header>
|
||||||
|
|
||||||
<style scoped>
|
<q-page-container>
|
||||||
</style>
|
<router-view />
|
||||||
|
</q-page-container>
|
||||||
|
</q-layout>
|
||||||
|
</template>
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
<template>
|
|
||||||
<q-dialog v-model="visible" persistent>
|
|
||||||
<q-card style="min-width: 350px; max-width: 700px;">
|
|
||||||
<q-card-section>
|
|
||||||
<div class="text-h6">{{ title }}</div>
|
|
||||||
</q-card-section>
|
|
||||||
|
|
||||||
<q-separator />
|
|
||||||
|
|
||||||
<q-card-section>
|
|
||||||
<slot />
|
|
||||||
</q-card-section>
|
|
||||||
|
|
||||||
<q-card-actions align="right">
|
|
||||||
<slot name="actions" />
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card>
|
|
||||||
</q-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
defineProps({
|
|
||||||
visible: Boolean,
|
|
||||||
title: String
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
<template>
|
|
||||||
<SharedDialogWrapper :visible="visible" title="Редактирование конкурса">
|
|
||||||
<q-input v-model="data.title" label="Название конкурса" dense autofocus clearable />
|
|
||||||
<q-input v-model="data.description" label="Описание" dense clearable type="textarea" class="q-mt-sm" />
|
|
||||||
<q-input v-model="data.start_date" label="Дата начала" type="date" dense clearable class="q-mt-sm" />
|
|
||||||
<q-input v-model="data.end_date" label="Дата окончания" type="date" dense clearable class="q-mt-sm" />
|
|
||||||
|
|
||||||
<template #actions>
|
|
||||||
<q-btn flat label="Удалить" color="negative" @click="onDelete" v-if="showDelete" />
|
|
||||||
<q-space />
|
|
||||||
<q-btn flat label="Закрыть" color="primary" @click="onClose" />
|
|
||||||
<q-btn flat label="Сохранить" color="primary" @click="onSave" />
|
|
||||||
</template>
|
|
||||||
</SharedDialogWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import SharedDialogWrapper from './SharedDialogWrapper.vue'
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
visible: Boolean,
|
|
||||||
data: Object,
|
|
||||||
showDelete: Boolean
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['save', 'close', 'delete'])
|
|
||||||
|
|
||||||
function onSave() {
|
|
||||||
emit('save')
|
|
||||||
}
|
|
||||||
function onClose() {
|
|
||||||
emit('close')
|
|
||||||
}
|
|
||||||
function onDelete() {
|
|
||||||
emit('delete')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<SharedDialogWrapper :visible="visible" title="Редактирование проекта">
|
|
||||||
<q-input v-model="data.title" label="Название проекта" dense autofocus clearable />
|
|
||||||
<q-input v-model="data.description" label="Описание" dense clearable type="textarea" class="q-mt-sm" />
|
|
||||||
<q-input v-model="data.repo_url" label="URL репозитория" dense clearable class="q-mt-sm" />
|
|
||||||
|
|
||||||
<template #actions>
|
|
||||||
<q-btn flat label="Удалить" color="negative" @click="onDelete" v-if="showDelete" />
|
|
||||||
<q-space />
|
|
||||||
<q-btn flat label="Закрыть" color="primary" @click="onClose" />
|
|
||||||
<q-btn flat label="Сохранить" color="primary" @click="onSave" />
|
|
||||||
</template>
|
|
||||||
</SharedDialogWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import SharedDialogWrapper from './SharedDialogWrapper.vue'
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
visible: Boolean,
|
|
||||||
data: Object,
|
|
||||||
showDelete: Boolean
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['save', 'close', 'delete'])
|
|
||||||
|
|
||||||
function onSave() {
|
|
||||||
emit('save')
|
|
||||||
}
|
|
||||||
function onClose() {
|
|
||||||
emit('close')
|
|
||||||
}
|
|
||||||
function onDelete() {
|
|
||||||
emit('delete')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
<template>
|
|
||||||
<SharedDialogWrapper :visible="visible" title="Редактирование команды">
|
|
||||||
<q-input v-model="data.title" label="Название команды" dense autofocus clearable />
|
|
||||||
<q-input v-model="data.description" label="Описание" dense clearable type="textarea" class="q-mt-sm" />
|
|
||||||
<q-input v-model="data.logo" label="Логотип" dense clearable class="q-mt-sm" />
|
|
||||||
<q-input v-model="data.git_url" label="Git URL" dense clearable class="q-mt-sm" />
|
|
||||||
|
|
||||||
<template #actions>
|
|
||||||
<q-btn flat label="Удалить" color="negative" @click="onDelete" v-if="showDelete" />
|
|
||||||
<q-space />
|
|
||||||
<q-btn flat label="Закрыть" color="primary" @click="onClose" />
|
|
||||||
<q-btn flat label="Сохранить" color="primary" @click="onSave" />
|
|
||||||
</template>
|
|
||||||
</SharedDialogWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import SharedDialogWrapper from './SharedDialogWrapper.vue'
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
visible: Boolean,
|
|
||||||
data: Object,
|
|
||||||
showDelete: Boolean
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['save', 'close', 'delete'])
|
|
||||||
|
|
||||||
function onSave() {
|
|
||||||
emit('save')
|
|
||||||
}
|
|
||||||
function onClose() {
|
|
||||||
emit('close')
|
|
||||||
}
|
|
||||||
function onDelete() {
|
|
||||||
emit('delete')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<SharedDialogWrapper :visible="visible" title="Редактирование пользователя">
|
|
||||||
<q-input v-model="data.login" label="Логин" dense autofocus clearable />
|
|
||||||
<q-input v-model="data.name" label="Имя" dense clearable class="q-mt-sm" />
|
|
||||||
<q-input v-model="data.email" label="Email" dense clearable class="q-mt-sm" />
|
|
||||||
|
|
||||||
<template #actions>
|
|
||||||
<q-btn flat label="Удалить" color="negative" @click="onDelete" v-if="showDelete" />
|
|
||||||
<q-space />
|
|
||||||
<q-btn flat label="Закрыть" color="primary" @click="onClose" />
|
|
||||||
<q-btn flat label="Сохранить" color="primary" @click="onSave" />
|
|
||||||
</template>
|
|
||||||
</SharedDialogWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import SharedDialogWrapper from '@/components/dialogs/SharedDialogWrapper.vue'
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
visible: Boolean,
|
|
||||||
data: Object,
|
|
||||||
showDelete: Boolean
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['save', 'close', 'delete'])
|
|
||||||
|
|
||||||
function onSave() {
|
|
||||||
emit('save')
|
|
||||||
}
|
|
||||||
function onClose() {
|
|
||||||
emit('close')
|
|
||||||
}
|
|
||||||
function onDelete() {
|
|
||||||
emit('delete')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -25,7 +25,12 @@ import {
|
|||||||
QCardActions,
|
QCardActions,
|
||||||
QDialog,
|
QDialog,
|
||||||
QIcon,
|
QIcon,
|
||||||
QSpace
|
QSpace,
|
||||||
|
QAvatar,
|
||||||
|
QTooltip,
|
||||||
|
QBanner,
|
||||||
|
QSlideTransition,
|
||||||
|
Ripple
|
||||||
} from 'quasar'
|
} from 'quasar'
|
||||||
|
|
||||||
|
|
||||||
@ -42,7 +47,11 @@ app.use(Quasar, {
|
|||||||
QInput, QBtn, QForm, QCard, QCardSection,
|
QInput, QBtn, QForm, QCard, QCardSection,
|
||||||
QLayout, QPageContainer, QPage,
|
QLayout, QPageContainer, QPage,
|
||||||
QTabs, QTab, QTabPanels, QTabPanel, QHeader,QTable,
|
QTabs, QTab, QTabPanels, QTabPanel, QHeader,QTable,
|
||||||
QSeparator, QCardActions, QDialog, QIcon, QSpace
|
QSeparator, QCardActions, QDialog, QIcon, QSpace,
|
||||||
|
QAvatar, QTooltip, QBanner, QSlideTransition
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
Ripple
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,13 @@
|
|||||||
<!-- Пользователи -->
|
<!-- Пользователи -->
|
||||||
<q-tab-panel name="users">
|
<q-tab-panel name="users">
|
||||||
<div class="violet-card q-pa-md">
|
<div class="violet-card q-pa-md">
|
||||||
|
<div class="q-gutter-sm q-mb-sm row items-center justify-between">
|
||||||
|
<q-btn
|
||||||
|
label="Создание пользователя"
|
||||||
|
color="primary"
|
||||||
|
@click="createHandler"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<q-table
|
<q-table
|
||||||
title="Пользователи"
|
title="Пользователи"
|
||||||
:rows="users"
|
:rows="users"
|
||||||
@ -40,16 +47,13 @@
|
|||||||
<!-- Команды -->
|
<!-- Команды -->
|
||||||
<q-tab-panel name="teams">
|
<q-tab-panel name="teams">
|
||||||
<div class="violet-card q-pa-md">
|
<div class="violet-card q-pa-md">
|
||||||
|
|
||||||
<div class="q-gutter-sm q-mb-sm row items-center justify-between">
|
<div class="q-gutter-sm q-mb-sm row items-center justify-between">
|
||||||
<q-btn
|
<q-btn
|
||||||
label="Создание команды"
|
label="Создание команды"
|
||||||
color="primary"
|
color="primary"
|
||||||
@click="createHandler"
|
@click="createHandler"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-table
|
<q-table
|
||||||
title="Команды"
|
title="Команды"
|
||||||
:rows="teams"
|
:rows="teams"
|
||||||
@ -67,6 +71,13 @@
|
|||||||
<!-- Проекты -->
|
<!-- Проекты -->
|
||||||
<q-tab-panel name="projects">
|
<q-tab-panel name="projects">
|
||||||
<div class="violet-card q-pa-md">
|
<div class="violet-card q-pa-md">
|
||||||
|
<div class="q-gutter-sm q-mb-sm row items-center justify-between">
|
||||||
|
<q-btn
|
||||||
|
label="Создание проекта"
|
||||||
|
color="primary"
|
||||||
|
@click="createHandler"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<q-table
|
<q-table
|
||||||
title="Проекты"
|
title="Проекты"
|
||||||
:rows="projects"
|
:rows="projects"
|
||||||
@ -83,6 +94,13 @@
|
|||||||
<!-- Конкурсы -->
|
<!-- Конкурсы -->
|
||||||
<q-tab-panel name="contests">
|
<q-tab-panel name="contests">
|
||||||
<div class="violet-card q-pa-md">
|
<div class="violet-card q-pa-md">
|
||||||
|
<div class="q-gutter-sm q-mb-sm row items-center justify-between">
|
||||||
|
<q-btn
|
||||||
|
label="Создание конкурса"
|
||||||
|
color="primary"
|
||||||
|
@click="createHandler"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<q-table
|
<q-table
|
||||||
title="Конкурсы"
|
title="Конкурсы"
|
||||||
:rows="contests"
|
:rows="contests"
|
||||||
@ -176,21 +194,21 @@
|
|||||||
flat
|
flat
|
||||||
label="Удалить"
|
label="Удалить"
|
||||||
color="negative"
|
color="negative"
|
||||||
@click="deleteUser"
|
@click="deleteItem"
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="dialogType === 'projects'"
|
v-if="dialogType === 'projects'"
|
||||||
flat
|
flat
|
||||||
label="Удалить"
|
label="Удалить"
|
||||||
color="negative"
|
color="negative"
|
||||||
@click="deleteProject"
|
@click="deleteItem"
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="dialogType === 'contests'"
|
v-if="dialogType === 'contests'"
|
||||||
flat
|
flat
|
||||||
label="Удалить"
|
label="Удалить"
|
||||||
color="negative"
|
color="negative"
|
||||||
@click="deleteContest"
|
@click="deleteItem"
|
||||||
/>
|
/>
|
||||||
<q-space />
|
<q-space />
|
||||||
<q-btn flat label="Закрыть" color="primary" @click="closeDialog" />
|
<q-btn flat label="Закрыть" color="primary" @click="closeDialog" />
|
||||||
@ -238,10 +256,9 @@ const teamColumns = [
|
|||||||
const projects = ref([])
|
const projects = ref([])
|
||||||
const loadingProjects = ref(false)
|
const loadingProjects = ref(false)
|
||||||
const projectColumns = [
|
const projectColumns = [
|
||||||
{ name: 'name', label: 'Название проекта', field: 'name', sortable: true },
|
{ name: 'title', label: 'Название проекта', field: 'title', sortable: true },
|
||||||
{ name: 'summary', label: 'Описание', field: 'summary', sortable: true },
|
{ name: 'description', label: 'Описание', field: 'description', sortable: true },
|
||||||
{ name: 'deadline', label: 'Дедлайн', field: 'deadline', sortable: true },
|
{ name: 'repository_url', label: 'Репозиторий', field: 'repository_url', sortable: true },
|
||||||
// добавьте нужные поля
|
|
||||||
]
|
]
|
||||||
|
|
||||||
// Общие состояния для диалогов
|
// Общие состояния для диалогов
|
||||||
|
|||||||
@ -1,46 +1,329 @@
|
|||||||
|
<template>
|
||||||
|
<q-page class="home-page bg-violet-strong q-pa-md">
|
||||||
|
|
||||||
|
<!-- Логотип по центру -->
|
||||||
|
<div class="flex justify-center q-mb-md">
|
||||||
|
<q-avatar size="140px" class="team-logo shadow-12">
|
||||||
|
<img :src="teamLogo" alt="Логотип команды" />
|
||||||
|
</q-avatar>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Название команды -->
|
||||||
|
<div class="flex justify-center q-mb-xl">
|
||||||
|
<q-card class="team-name-card">
|
||||||
|
<q-card-section class="text-h4 text-center text-indigo-10 q-pa-md">
|
||||||
|
{{ teamName }}
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Участники (по центру, без прокрутки) -->
|
||||||
|
<div class="flex justify-center flex-wrap q-gutter-md q-mb-xl">
|
||||||
|
<q-card
|
||||||
|
v-for="member in members"
|
||||||
|
:key="member.id"
|
||||||
|
class="member-card violet-card"
|
||||||
|
bordered
|
||||||
|
style="width: 180px;"
|
||||||
|
v-ripple
|
||||||
|
>
|
||||||
|
<q-card-section class="q-pa-md flex flex-center">
|
||||||
|
<q-avatar size="64px" class="shadow-6">
|
||||||
|
<img :src="member.avatar" :alt="member.name" />
|
||||||
|
</q-avatar>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section class="q-pt-none">
|
||||||
|
<div class="text-subtitle1 text-center text-indigo-11">{{ member.name }}</div>
|
||||||
|
<div class="text-caption text-center text-indigo-9">{{ member.role }}</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Конкурсы (по центру, без прокрутки) -->
|
||||||
|
<div class="flex justify-center flex-wrap q-gutter-md q-mb-xl">
|
||||||
|
<q-card
|
||||||
|
v-for="contest in contests"
|
||||||
|
:key="contest.id"
|
||||||
|
class="contest-card violet-card"
|
||||||
|
bordered
|
||||||
|
style="width: 220px;"
|
||||||
|
v-ripple
|
||||||
|
>
|
||||||
|
<q-card-section class="q-pa-md">
|
||||||
|
<div class="text-h6">{{ contest.title }}</div>
|
||||||
|
<div class="text-subtitle2 text-indigo-8">{{ contest.description }}</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Разделитель -->
|
||||||
|
<q-separator class="q-my-lg" color="indigo-4" style="width: 80%; margin: 0 auto;" />
|
||||||
|
<div class="q-mt-md"></div>
|
||||||
|
|
||||||
|
<!-- Активность и история коммитов -->
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<q-card class="activity-card violet-card q-mb-xl" style="max-width: 920px; width: 100%;">
|
||||||
|
<q-card-section class="q-pa-md">
|
||||||
|
<div class="text-h6 text-indigo-10 q-mb-md">Активность команды и история коммитов</div>
|
||||||
|
|
||||||
|
<div class="activity-container row no-wrap items-start q-mb-md">
|
||||||
|
<div class="dates-column column q-pr-md" style="min-width: 50px;">
|
||||||
|
<div
|
||||||
|
v-for="item in activityData"
|
||||||
|
:key="item.date"
|
||||||
|
class="activity-date text-caption text-indigo-9"
|
||||||
|
style="height: 16px; line-height: 16px;"
|
||||||
|
>
|
||||||
|
{{ item.date.slice(5) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="activity-grid row wrap" style="flex: 1; gap: 4px;">
|
||||||
|
<div
|
||||||
|
v-for="item in activityData"
|
||||||
|
:key="item.date"
|
||||||
|
class="activity-square"
|
||||||
|
:title="`Дата: ${item.date}, активность: ${item.count}`"
|
||||||
|
:style="{ backgroundColor: getActivityColor(item.count) }"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="commits-list q-pa-sm" style="max-height: 150px; overflow-y: auto;">
|
||||||
|
<div
|
||||||
|
v-for="commit in commits"
|
||||||
|
:key="commit.id"
|
||||||
|
class="commit-item text-caption text-indigo-9 q-mb-xs"
|
||||||
|
>
|
||||||
|
<strong>{{ commit.date }}:</strong> {{ commit.message }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Кнопка выхода / авторизации -->
|
||||||
|
<q-btn
|
||||||
|
:icon="isAuthenticated ? 'logout' : 'login'"
|
||||||
|
class="fixed-bottom-right q-ma-md"
|
||||||
|
size="20px"
|
||||||
|
color="indigo-10"
|
||||||
|
round
|
||||||
|
@click="handleAuthAction"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</q-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter} from 'vue-router'
|
||||||
|
import { Ripple, Notify } from 'quasar'
|
||||||
|
|
||||||
|
defineExpose({ directives: { ripple: Ripple } })
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// Реактивное вычисление статуса авторизации
|
const isAuthenticated = ref(!!localStorage.getItem('access_token'))
|
||||||
const isAuthenticated = computed(() => !!localStorage.getItem('access_token'))
|
|
||||||
|
|
||||||
const goToLogin = () => router.push('/login')
|
const handleAuthAction = () => {
|
||||||
const logout = () => {
|
if (isAuthenticated.value) {
|
||||||
localStorage.removeItem('access_token')
|
localStorage.removeItem('access_token')
|
||||||
router.go(0) // Принудительное обновление страницы для обновления состояния
|
localStorage.removeItem('user_id')
|
||||||
|
isAuthenticated.value = false
|
||||||
|
|
||||||
|
Notify.create({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Выход успешно осуществлен',
|
||||||
|
icon: 'check_circle',
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
router.push('/login')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Данные команды ---
|
||||||
|
const teamLogo = ref('https://cdn.quasar.dev/logo-v2/svg/logo.svg')
|
||||||
|
const teamName = ref('Digital Dream Team')
|
||||||
|
|
||||||
|
// --- Участники ---
|
||||||
|
const members = ref([
|
||||||
|
{ id: 1, name: 'Иван Иванов', role: 'Team Lead', avatar: 'https://randomuser.me/api/portraits/men/32.jpg' },
|
||||||
|
{ id: 2, name: 'Мария Петрова', role: 'Frontend', avatar: 'https://randomuser.me/api/portraits/women/44.jpg' },
|
||||||
|
{ id: 3, name: 'Алексей Смирнов', role: 'Backend', avatar: 'https://randomuser.me/api/portraits/men/65.jpg' },
|
||||||
|
{ id: 4, name: 'Анна Кузнецова', role: 'Designer', avatar: 'https://randomuser.me/api/portraits/women/56.jpg' },
|
||||||
|
{ id: 5, name: 'Дмитрий Орлов', role: 'QA', avatar: 'https://randomuser.me/api/portraits/men/78.jpg' },
|
||||||
|
])
|
||||||
|
|
||||||
|
// --- Конкурсы ---
|
||||||
|
const contests = ref([
|
||||||
|
{ id: 1, title: 'Hackathon 2024', description: 'Ежегодный хакатон для стартапов' },
|
||||||
|
{ id: 2, title: 'CodeFest', description: 'Соревнование по программированию' },
|
||||||
|
{ id: 3, title: 'UI/UX Challenge', description: 'Конкурс дизайна интерфейсов' },
|
||||||
|
{ id: 4, title: 'AI Innovation', description: 'Инициатива в области искусственного интеллекта' },
|
||||||
|
])
|
||||||
|
|
||||||
|
// --- Активность ---
|
||||||
|
const activityData = ref([])
|
||||||
|
const today = new Date()
|
||||||
|
const activityDays = 30
|
||||||
|
function pad(num) { return num < 10 ? '0' + num : num }
|
||||||
|
|
||||||
|
for (let i = activityDays - 1; i >= 0; i--) {
|
||||||
|
const d = new Date(today)
|
||||||
|
d.setDate(d.getDate() - i)
|
||||||
|
const count = Math.floor(Math.random() * 6)
|
||||||
|
activityData.value.push({ date: d.toISOString().slice(0, 10), count })
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Коммиты ---
|
||||||
|
const commits = ref([
|
||||||
|
{ id: 1, message: 'Добавлен график активности', date: '2025-05-28' },
|
||||||
|
{ id: 2, message: 'Исправлена верстка карточек', date: '2025-05-27' },
|
||||||
|
{ id: 3, message: 'Обновлены данные команды', date: '2025-05-26' },
|
||||||
|
{ id: 4, message: 'Оптимизирован компонент участников', date: '2025-05-25' },
|
||||||
|
])
|
||||||
|
|
||||||
|
function getActivityColor(count) {
|
||||||
|
if (count === 0) return '#ddd'
|
||||||
|
const opacity = 0.15 + (count / 5) * 0.6
|
||||||
|
return `rgba(124, 58, 237, ${opacity.toFixed(2)})`
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="home-page q-pa-md q-gutter-md">
|
|
||||||
<h4 class="text-center">Добро пожаловать!</h4>
|
|
||||||
|
|
||||||
<div v-if="isAuthenticated" class="q-gutter-sm">
|
|
||||||
<q-btn label="Редактировать профиль" color="secondary" />
|
|
||||||
<q-btn label="Выход" color="negative" @click="logout" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<q-btn
|
|
||||||
v-else
|
|
||||||
label="Авторизация"
|
|
||||||
color="primary"
|
|
||||||
@click="goToLogin"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.home-page {
|
.bg-violet-strong {
|
||||||
|
background: linear-gradient(135deg, #4f046f 0%, #7c3aed 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
color: #3e2465;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-logo {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 140px;
|
||||||
|
height: 140px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-height: 100vh;
|
transition: transform 0.3s ease;
|
||||||
gap: 20px;
|
|
||||||
}
|
}
|
||||||
</style>
|
.team-logo:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
box-shadow: 0 0 14px #a287ffaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-name-card {
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #ede9fe;
|
||||||
|
box-shadow:
|
||||||
|
0 8px 24px rgba(124, 58, 237, 0.18),
|
||||||
|
0 2px 8px rgba(124, 58, 237, 0.12);
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.violet-card {
|
||||||
|
border-radius: 22px;
|
||||||
|
background: #ede9fe;
|
||||||
|
box-shadow:
|
||||||
|
0 8px 24px rgba(124, 58, 237, 0.18),
|
||||||
|
0 2px 8px rgba(124, 58, 237, 0.12);
|
||||||
|
transition: box-shadow 0.3s ease, transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.violet-card:hover {
|
||||||
|
box-shadow:
|
||||||
|
0 14px 40px rgba(124, 58, 237, 0.30),
|
||||||
|
0 6px 16px rgba(124, 58, 237, 0.20);
|
||||||
|
transform: translateY(-6px);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-card, .contest-card {
|
||||||
|
min-height: 140px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-scroll {
|
||||||
|
display: flex;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
.horizontal-scroll::-webkit-scrollbar {
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
.horizontal-scroll::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(124, 58, 237, 0.4);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-card {
|
||||||
|
max-width: 920px;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-container {
|
||||||
|
/* align-items: center; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dates-column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
color: #5e35b1;
|
||||||
|
font-weight: 600;
|
||||||
|
user-select: none;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-date {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
user-select: none;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: rgba(124, 58, 237, 0.4) transparent;
|
||||||
|
}
|
||||||
|
.activity-grid::-webkit-scrollbar {
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
.activity-grid::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(124, 58, 237, 0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-square {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 2px;
|
||||||
|
box-shadow: 0 0 3px rgba(124, 58, 237, 0.3);
|
||||||
|
cursor: default;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commits-list {
|
||||||
|
background: #f5f3ff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
color: #4b0082;
|
||||||
|
box-shadow: inset 0 0 6px #c7b3f7;
|
||||||
|
}
|
||||||
|
.commit-item strong {
|
||||||
|
color: #7c3aed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -61,20 +61,16 @@ const authorisation = async () => {
|
|||||||
icon: 'check_circle'
|
icon: 'check_circle'
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('Role ID:', roleId)
|
|
||||||
if (roleId === 1) {
|
if (roleId === 1) {
|
||||||
console.log('Переход на /admin')
|
await router.push('/admin')
|
||||||
router.push('/admin')
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Переход на /')
|
await router.push('/')
|
||||||
router.push('/')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (roleId === 1) {
|
if (roleId === 1) {
|
||||||
router.push('/admin')
|
await router.push('/admin')
|
||||||
} else {
|
} else {
|
||||||
router.push('/')
|
await router.push('/')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Notify.create({
|
Notify.create({
|
||||||
@ -230,13 +226,6 @@ const authorisation = async () => {
|
|||||||
100% { transform: translateX(calc(-1 * var(--marquee-width, 370px))); }
|
100% { transform: translateX(calc(-1 * var(--marquee-width, 370px))); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.q-input,
|
|
||||||
.q-field__control,
|
|
||||||
.q-field__native,
|
|
||||||
.q-field__inner {
|
|
||||||
border-radius: 14px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-rounded {
|
.btn-rounded {
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
}
|
}
|
||||||
@ -279,12 +268,6 @@ const authorisation = async () => {
|
|||||||
background: #ede9fe !important;
|
background: #ede9fe !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lavender-input .q-field__control,
|
|
||||||
.lavender-input .q-field__native,
|
|
||||||
.lavender-input .q-field__inner {
|
|
||||||
background: #f6f0ff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-violet-strong {
|
.text-violet-strong {
|
||||||
color: #4f046f;
|
color: #4f046f;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user