1 parent
e12d2163bf
commit
410b182801
6 files changed
+143
-90
No files matched your search
+41
-14
@@ -1,21 +1,48 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const menu = [
|
import { ref } from 'vue'
|
||||||
{ id: 1, title: 'home', to: '/' },
|
|
||||||
{ id: 2, title: 'issues', to: '/issues' },
|
interface Props {
|
||||||
{ id: 3, title: 'summary', to: '/summary' },
|
isAuth: boolean
|
||||||
{ id: 4, title: 'reports', to: '/reports' },
|
}
|
||||||
]
|
|
||||||
|
const { isAuth } = defineProps<Props>()
|
||||||
|
|
||||||
|
const menu = ref([
|
||||||
|
{
|
||||||
|
title: 'Home',
|
||||||
|
value: 1,
|
||||||
|
props: { prependIcon: 'mdi-home', to: '/', requiresAuth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Issues',
|
||||||
|
value: 2,
|
||||||
|
props: { prependIcon: 'mdi-list-status', to: '/issues', requiresAuth: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Games',
|
||||||
|
value: 3,
|
||||||
|
props: { prependIcon: 'mdi-view-dashboard', to: '/games', requiresAuth: false },
|
||||||
|
},
|
||||||
|
])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-list class="mt-1" width="200" density="compact">
|
<v-menu>
|
||||||
<v-list-item v-for="item in menu" :key="item.id" :to="item.to">
|
<template v-slot:activator="{ props }">
|
||||||
<v-list-item-title class="d-flex align-center ga-4">
|
<v-app-bar-nav-icon variant="text" density="comfortable" v-bind="props" />
|
||||||
<v-icon icon="mdi-information-outline" />
|
</template>
|
||||||
<div>{{ item.title }}</div>
|
|
||||||
</v-list-item-title>
|
<v-list class="mt-1" width="200" density="compact">
|
||||||
</v-list-item>
|
<template v-for="item in menu" :key="item.value">
|
||||||
</v-list>
|
<v-list-item v-if="!item.props.requiresAuth || isAuth === item.props.requiresAuth" :to="item.props.to">
|
||||||
|
<v-list-item-title class="d-flex align-center ga-4">
|
||||||
|
<v-icon :icon="item.props.prependIcon" />
|
||||||
|
<div>{{ item.title }}</div>
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
@@ -32,7 +32,7 @@ const activity = ref()
|
|||||||
const { ckey } = defineProps<Props>()
|
const { ckey } = defineProps<Props>()
|
||||||
|
|
||||||
const splitContainer = useTemplateRef<HTMLElement>('splitContainer')
|
const splitContainer = useTemplateRef<HTMLElement>('splitContainer')
|
||||||
const { gridTemplate, handleProps } = useSplitPane(splitContainer, { storageKey: 'issue-details' })
|
const { gridTemplate, handleProps } = useSplitPane(splitContainer, { storageKey: 'issue-details', min: 0.3, max: 0.7 })
|
||||||
|
|
||||||
const createdAtFormatted = computed(() => {
|
const createdAtFormatted = computed(() => {
|
||||||
if (!issue.value?.createdAt) return ''
|
if (!issue.value?.createdAt) return ''
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isAuth: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const { isAuth } = defineProps<Props>()
|
||||||
|
|
||||||
|
const menu = ref([
|
||||||
|
{
|
||||||
|
title: 'Home',
|
||||||
|
value: 1,
|
||||||
|
props: { prependIcon: 'mdi-home', to: '/', requiresAuth: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Issues',
|
||||||
|
value: 2,
|
||||||
|
props: { prependIcon: 'mdi-list-status', to: '/issues', requiresAuth: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Games',
|
||||||
|
value: 3,
|
||||||
|
props: { prependIcon: 'mdi-view-dashboard', to: '/games', requiresAuth: false },
|
||||||
|
},
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-navigation-drawer rounded="0" width="200" persistent permanent class="pt-4">
|
||||||
|
<template v-for="item in menu" :key="item.value">
|
||||||
|
<v-list-item
|
||||||
|
density="compact"
|
||||||
|
rounded="0"
|
||||||
|
v-if="!item.props.requiresAuth || isAuth === item.props.requiresAuth"
|
||||||
|
:to="item.props.to"
|
||||||
|
>
|
||||||
|
<v-list-item-title class="d-flex align-center ga-4">
|
||||||
|
<v-icon :icon="item.props.prependIcon" />
|
||||||
|
<div>{{ item.title }}</div>
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
</v-navigation-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@@ -32,7 +32,7 @@ onMounted(async () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="projects.length" class="d-flex align-center ga-2">
|
<div v-if="projects.length" class="d-flex align-center ga-2">
|
||||||
<div>Project:</div>
|
<div>Current project:</div>
|
||||||
<v-menu>
|
<v-menu>
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<v-btn density="comfortable" v-bind="props" slim>
|
<v-btn density="comfortable" v-bind="props" slim>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { authClient } from '@/lib/auth-client.ts'
|
import { authClient } from '@/lib/auth-client.ts'
|
||||||
import { computed, ref } from 'vue'
|
import { computed } from 'vue'
|
||||||
import ProjectMenu from '@/components/ProjectMenu.vue'
|
|
||||||
import AppBreadcrumbs from '@/components/AppBreadcrumbs.vue'
|
import AppBreadcrumbs from '@/components/AppBreadcrumbs.vue'
|
||||||
import BackButton from '@/components/BackButton.vue'
|
import BackButton from '@/components/BackButton.vue'
|
||||||
import { useThemeMode } from '@/composables/useThemeMode.ts'
|
import { useThemeMode } from '@/composables/useThemeMode.ts'
|
||||||
import { THEME_ICONS } from '@/lib/theme.ts'
|
import { THEME_ICONS } from '@/lib/theme.ts'
|
||||||
|
import NavigationMenu from '@/components/NavigationMenu.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -17,24 +17,6 @@ const title = 'Ulitka'
|
|||||||
|
|
||||||
const isAuth = computed(() => !!session.value.data)
|
const isAuth = computed(() => !!session.value.data)
|
||||||
|
|
||||||
const menu = ref([
|
|
||||||
{
|
|
||||||
title: 'Home',
|
|
||||||
value: 1,
|
|
||||||
props: { prependIcon: 'mdi-home', to: '/', requiresAuth: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'issues',
|
|
||||||
value: 2,
|
|
||||||
props: { prependIcon: 'mdi-list-status', to: '/issues', requiresAuth: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'games',
|
|
||||||
value: 3,
|
|
||||||
props: { prependIcon: 'mdi-view-dashboard', to: '/games', requiresAuth: false },
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
function goToSignIn() {
|
function goToSignIn() {
|
||||||
router.push({ path: '/sign-in' })
|
router.push({ path: '/sign-in' })
|
||||||
}
|
}
|
||||||
@@ -69,75 +51,47 @@ const fluid = computed(() => {
|
|||||||
<template>
|
<template>
|
||||||
<v-layout>
|
<v-layout>
|
||||||
<v-app-bar density="compact" elevation="0" border rounded="0">
|
<v-app-bar density="compact" elevation="0" border rounded="0">
|
||||||
<template v-slot:prepend>
|
<v-app-bar-title class="d-flex">
|
||||||
<v-menu>
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-app-bar-nav-icon variant="text" density="comfortable" v-bind="props" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<v-list class="mt-1" width="200" density="compact">
|
|
||||||
<template v-for="item in menu" :key="item.value">
|
|
||||||
<v-list-item v-if="!item.props.requiresAuth || isAuth === item.props.requiresAuth" :to="item.props.to">
|
|
||||||
<v-list-item-title class="d-flex align-center ga-4">
|
|
||||||
<v-icon :icon="item.props.prependIcon" />
|
|
||||||
<div>{{ item.title }}</div>
|
|
||||||
</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
</template>
|
|
||||||
</v-list>
|
|
||||||
</v-menu>
|
|
||||||
</template>
|
|
||||||
<v-divider class="mx-1" vertical />
|
|
||||||
<v-app-bar-title>
|
|
||||||
<router-link class="text-decoration-none text-link font-weight-bold d-flex align-baseline ga-2" to="/">
|
<router-link class="text-decoration-none text-link font-weight-bold d-flex align-baseline ga-2" to="/">
|
||||||
<v-icon icon="mdi-snail" />
|
<v-icon icon="mdi-snail" />
|
||||||
<div>{{ title }}</div>
|
<div>{{ title }}</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</v-app-bar-title>
|
</v-app-bar-title>
|
||||||
|
|
||||||
<project-menu v-if="session.data" />
|
|
||||||
|
|
||||||
<v-divider class="mx-2" vertical />
|
|
||||||
|
|
||||||
<div class="d-flex ga-4 align-center" v-if="session.data">
|
|
||||||
<div class="">
|
|
||||||
Hello,
|
|
||||||
<router-link class="text-decoration-none text-link text-capitalize" to="/profile">
|
|
||||||
{{ session?.data.user.name }}
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="!session.data">
|
<div v-if="!session.data">
|
||||||
<v-btn @click="goToSignIn">Sign In</v-btn>
|
<v-btn @click="goToSignIn">Sign In</v-btn>
|
||||||
<v-btn @click="goToSignUp">Sign Up</v-btn>
|
<v-btn @click="goToSignUp">Sign Up</v-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<v-divider class="mx-2" vertical />
|
<v-btn rounded="0" :icon="THEME_ICONS[themeMode]" :title="`Theme: ${themeMode}`" @click="cycleThemeMode" />
|
||||||
<v-btn
|
|
||||||
:icon="THEME_ICONS[themeMode]"
|
|
||||||
:title="`Theme: ${themeMode}`"
|
|
||||||
density="comfortable"
|
|
||||||
@click="cycleThemeMode"
|
|
||||||
/>
|
|
||||||
<v-divider class="mx-2" vertical />
|
|
||||||
|
|
||||||
<div v-if="session.data">
|
<div v-if="session.data">
|
||||||
<v-menu>
|
<v-menu>
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<v-btn density="comfortable" class="mr-1" icon v-bind="props">
|
<v-btn rounded="0" icon v-bind="props" class="mr-4">
|
||||||
<v-icon icon="mdi-account" />
|
<v-icon icon="mdi-account" />
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-list class="mt-1" width="200">
|
<v-list nav density="compact" class="pa-1">
|
||||||
<v-list-item @click="goToProfile">
|
<v-list-item density="compact">
|
||||||
|
<v-sheet border class="d-flex align-center ga-2 pa-2">
|
||||||
|
<v-avatar rounded="circle" color="primary">A</v-avatar>
|
||||||
|
<div>
|
||||||
|
<div>{{ session.data.user.name }}</div>
|
||||||
|
<div class="text-label-medium">{{ session.data.user.email }}</div>
|
||||||
|
</div>
|
||||||
|
</v-sheet>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item rounded="0" density="compact" @click="goToProfile">
|
||||||
<v-icon icon="mdi-account" />
|
<v-icon icon="mdi-account" />
|
||||||
Profile
|
Profile
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item @click="goToSettings">
|
<v-list-item rounded="0" density="compact" @click="goToSettings">
|
||||||
<v-icon icon="mdi-cog" />
|
<v-icon icon="mdi-cog" />
|
||||||
settings
|
settings
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item @click="goToSignOut">
|
<v-divider class="my-1" />
|
||||||
|
<v-list-item rounded="0" density="compact" @click="goToSignOut">
|
||||||
<v-icon icon="mdi-logout" />
|
<v-icon icon="mdi-logout" />
|
||||||
Sign Out
|
Sign Out
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
@@ -145,6 +99,9 @@ const fluid = computed(() => {
|
|||||||
</v-menu>
|
</v-menu>
|
||||||
</div>
|
</div>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
|
|
||||||
|
<navigation-menu :is-auth="isAuth" />
|
||||||
|
|
||||||
<v-main>
|
<v-main>
|
||||||
<v-container :fluid="fluid" class="layout-container">
|
<v-container :fluid="fluid" class="layout-container">
|
||||||
<div class="nav-row d-flex align-center ga-2 mb-2">
|
<div class="nav-row d-flex align-center ga-2 mb-2">
|
||||||
|
|||||||
+31
-9
@@ -10,6 +10,7 @@ import type { Issue } from '@/api/issue.api.ts'
|
|||||||
import type { Project } from '@/api/project.api.ts'
|
import type { Project } from '@/api/project.api.ts'
|
||||||
import DashboardCountCard from '@/components/DashboardCountCard.vue'
|
import DashboardCountCard from '@/components/DashboardCountCard.vue'
|
||||||
import LabelText from '@/components/LabelText.vue'
|
import LabelText from '@/components/LabelText.vue'
|
||||||
|
import ProjectMenu from '@/components/ProjectMenu.vue'
|
||||||
|
|
||||||
const ACTIVE_STATUSES: Issue['status'][] = ['OPEN', 'IN_PROGRESS']
|
const ACTIVE_STATUSES: Issue['status'][] = ['OPEN', 'IN_PROGRESS']
|
||||||
|
|
||||||
@@ -113,20 +114,28 @@ function onClickCard(status?: string) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="session.data" class="d-flex flex-column ga-2">
|
<div v-if="session.data" class="d-flex flex-column ga-4">
|
||||||
|
<project-menu />
|
||||||
|
|
||||||
<div class="dashboard_grid">
|
<div class="dashboard_grid">
|
||||||
<dashboard-count-card label="Всего задач" :value="stats?.total ?? 0" @click="onClickCard()" />
|
<dashboard-count-card label="Total issues" :value="stats?.total ?? 0" @click="onClickCard()" />
|
||||||
<dashboard-count-card label="Открыто" :value="statCount('OPEN')" @click="onClickCard('OPEN')" />
|
<dashboard-count-card label="Open" :value="statCount('OPEN')" @click="onClickCard('OPEN')" />
|
||||||
<dashboard-count-card label="В работе" :value="statCount('IN_PROGRESS')" @click="onClickCard('IN_PROGRESS')" />
|
<dashboard-count-card
|
||||||
<dashboard-count-card label="Просрочено" :value="overdueCount" :alert="overdueCount > 0" />
|
label="In Progress"
|
||||||
|
:value="statCount('IN_PROGRESS')"
|
||||||
|
@click="onClickCard('IN_PROGRESS')"
|
||||||
|
/>
|
||||||
|
<dashboard-count-card label="Overdue" :value="overdueCount" :alert="overdueCount > 0" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<v-divider />
|
||||||
|
|
||||||
<v-row density="compact">
|
<v-row density="compact">
|
||||||
<v-col cols="12" md="8">
|
<v-col cols="12" md="8">
|
||||||
<v-card border>
|
<v-card border>
|
||||||
<v-card-title class="d-flex align-center justify-space-between">
|
<v-card-title class="d-flex align-center justify-space-between">
|
||||||
<span>Мои задачи</span>
|
<span>My issues</span>
|
||||||
<v-btn size="small" variant="text" to="/issues">Все задачи</v-btn>
|
<v-btn size="small" variant="text" to="/issues">All issues</v-btn>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-divider />
|
<v-divider />
|
||||||
<v-list v-if="sortedMyIssues.length" density="compact">
|
<v-list v-if="sortedMyIssues.length" density="compact">
|
||||||
@@ -173,8 +182,8 @@ function onClickCard(status?: string) {
|
|||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-card border>
|
<v-card border>
|
||||||
<v-card-title class="d-flex align-center justify-space-between">
|
<v-card-title class="d-flex align-center justify-space-between">
|
||||||
<span>Проекты</span>
|
<span>Projects</span>
|
||||||
<v-btn size="small" variant="text" to="/settings/projects">Все проекты</v-btn>
|
<v-btn size="small" variant="text" to="/settings/projects">All projects</v-btn>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-divider />
|
<v-divider />
|
||||||
<v-list v-if="projects.length" density="compact">
|
<v-list v-if="projects.length" density="compact">
|
||||||
@@ -186,6 +195,19 @@ function onClickCard(status?: string) {
|
|||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
|
<v-row density="compact">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-card border>
|
||||||
|
<v-card-text>text</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-card border>
|
||||||
|
<v-card-text>text</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in new issue
Block a user