generated from alphane/template
Compare commits
2 Commits
02ef729bf4
...
b7b473d079
| Author | SHA1 | Date | |
|---|---|---|---|
| b7b473d079 | |||
| 1af13091e6 |
@@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<div class="logo">
|
||||||
|
<RouterLink
|
||||||
|
:to="to"
|
||||||
|
class="d-flex"
|
||||||
|
>
|
||||||
|
<div class="d-flex align-center mt-1 ml-3 terminal-prompt">
|
||||||
|
<span class="term-green">caleb</span>
|
||||||
|
<span class="term-cyan">@</span>
|
||||||
|
<span class="term-green mr-2">burke</span>
|
||||||
|
<span class="term-white">~</span>
|
||||||
|
<span class="term-cyan mr-2">$</span>
|
||||||
|
<span class="term-white">{{ typedText }}</span>
|
||||||
|
<span class="term-cursor">█</span>
|
||||||
|
</div>
|
||||||
|
</RouterLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, onUnmounted, ref } from "vue"
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
to?: string
|
||||||
|
animated?: boolean
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
to: "/dashboard",
|
||||||
|
animated: false,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const TYPED_PHRASES = [
|
||||||
|
" Hello!",
|
||||||
|
" привет",
|
||||||
|
" クリア",
|
||||||
|
" Εβίβα!",
|
||||||
|
" 干杯",
|
||||||
|
" Будьмо!",
|
||||||
|
" Na zdraví!",
|
||||||
|
" 乾杯!",
|
||||||
|
]
|
||||||
|
const TYPE_DELAY_MS = 150
|
||||||
|
const DELETE_DELAY_MS = 100
|
||||||
|
const PAUSE_AFTER_TYPED_MS = 1500
|
||||||
|
const INITIAL_DELAY_MS = 800
|
||||||
|
|
||||||
|
const typedText = ref("")
|
||||||
|
let currentPhrase = ""
|
||||||
|
let typingTimeoutId: ReturnType<typeof setTimeout>
|
||||||
|
|
||||||
|
function pickRandomPhrase() {
|
||||||
|
return TYPED_PHRASES[Math.floor(Math.random() * TYPED_PHRASES.length)]
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeCharacter(index: number) {
|
||||||
|
typedText.value = currentPhrase.slice(0, index)
|
||||||
|
|
||||||
|
if (index < currentPhrase.length) {
|
||||||
|
typingTimeoutId = setTimeout(() => typeCharacter(index + 1), TYPE_DELAY_MS)
|
||||||
|
} else {
|
||||||
|
typingTimeoutId = setTimeout(() => deleteCharacter(index), PAUSE_AFTER_TYPED_MS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteCharacter(index: number) {
|
||||||
|
typedText.value = currentPhrase.slice(0, index)
|
||||||
|
|
||||||
|
if (index > 0) {
|
||||||
|
typingTimeoutId = setTimeout(() => deleteCharacter(index - 1), DELETE_DELAY_MS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!props.animated) return
|
||||||
|
|
||||||
|
currentPhrase = pickRandomPhrase()
|
||||||
|
typingTimeoutId = setTimeout(() => typeCharacter(0), INITIAL_DELAY_MS)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearTimeout(typingTimeoutId)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.logo a {
|
||||||
|
text-decoration: none !important;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-prompt {
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", "DejaVu Sans Mono", monospace;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-prompt .term-green {
|
||||||
|
color: #4e9a06;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-prompt .term-cyan {
|
||||||
|
color: #06989a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-prompt .term-white {
|
||||||
|
color: #d3d7cf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .terminal-prompt .term-cursor {
|
||||||
|
color: #d3d7cf;
|
||||||
|
animation: term-blink 1s step-end infinite;
|
||||||
|
} */
|
||||||
|
|
||||||
|
@keyframes term-blink {
|
||||||
|
0%,
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50.01%,
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,32 +1,66 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app-bar
|
<div v-if="mobile">
|
||||||
id="top"
|
<v-app-bar
|
||||||
elevation="6"
|
id="top"
|
||||||
height="60"
|
elevation="6"
|
||||||
class="main-head pl-2"
|
height="60"
|
||||||
>
|
extension-height="48"
|
||||||
<div class="mr-3">
|
class="main-head pl-2"
|
||||||
<AppLogo />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<v-tabs
|
|
||||||
class="ml-2"
|
|
||||||
color="primary"
|
|
||||||
>
|
>
|
||||||
<v-tab
|
<div class="mr-3">
|
||||||
:to="{ name: 'DashboardPage' }"
|
<AppLogo />
|
||||||
text="Dashboard"
|
</div>
|
||||||
/>
|
|
||||||
<v-tab
|
|
||||||
:to="{ name: 'FlashcardsPage' }"
|
|
||||||
text="Flashcards"
|
|
||||||
/>
|
|
||||||
</v-tabs>
|
|
||||||
|
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
|
|
||||||
<!-- TODO Add notifications -->
|
<ProfileMenu />
|
||||||
<!-- <v-btn
|
|
||||||
|
<template #extension>
|
||||||
|
<v-tabs
|
||||||
|
class="ml-2"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<v-tab
|
||||||
|
:to="{ name: 'DashboardPage' }"
|
||||||
|
text="Dashboard"
|
||||||
|
/>
|
||||||
|
<v-tab
|
||||||
|
:to="{ name: 'FlashcardsPage' }"
|
||||||
|
text="Flashcards"
|
||||||
|
/>
|
||||||
|
</v-tabs>
|
||||||
|
</template>
|
||||||
|
</v-app-bar>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<v-app-bar
|
||||||
|
id="top"
|
||||||
|
elevation="6"
|
||||||
|
height="60"
|
||||||
|
class="main-head pl-2"
|
||||||
|
>
|
||||||
|
<div class="mr-3">
|
||||||
|
<AppLogo />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<v-tabs
|
||||||
|
class="ml-2"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<v-tab
|
||||||
|
:to="{ name: 'DashboardPage' }"
|
||||||
|
text="Dashboard"
|
||||||
|
/>
|
||||||
|
<v-tab
|
||||||
|
:to="{ name: 'FlashcardsPage' }"
|
||||||
|
text="Flashcards"
|
||||||
|
/>
|
||||||
|
</v-tabs>
|
||||||
|
|
||||||
|
<v-spacer />
|
||||||
|
|
||||||
|
<!-- TODO Add notifications -->
|
||||||
|
<!-- <v-btn
|
||||||
icon
|
icon
|
||||||
class="mr-1"
|
class="mr-1"
|
||||||
>
|
>
|
||||||
@@ -42,11 +76,16 @@
|
|||||||
</v-badge>
|
</v-badge>
|
||||||
</v-btn> -->
|
</v-btn> -->
|
||||||
|
|
||||||
<ProfileMenu />
|
<ProfileMenu />
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useDisplay } from "vuetify"
|
||||||
|
|
||||||
import AppLogo from "@/components/common/AppLogo.vue"
|
import AppLogo from "@/components/common/AppLogo.vue"
|
||||||
import ProfileMenu from "@/components/layout/ProfileMenu.vue"
|
import ProfileMenu from "@/components/layout/ProfileMenu.vue"
|
||||||
|
|
||||||
|
const { mobile } = useDisplay()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
<v-app-bar
|
||||||
|
id="top"
|
||||||
|
elevation="6"
|
||||||
|
height="60"
|
||||||
|
class="main-head pl-2"
|
||||||
|
>
|
||||||
|
<div class="mr-3">
|
||||||
|
<PublicAppLogo
|
||||||
|
to="/"
|
||||||
|
:animated="isHomePage"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<v-spacer />
|
||||||
|
</v-app-bar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from "vue"
|
||||||
|
import { useRoute } from "vue-router"
|
||||||
|
|
||||||
|
import PublicAppLogo from "@/components/common/PublicAppLogo.vue"
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const isHomePage = computed(() => route.name === "HomePage")
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<v-app>
|
||||||
|
<PublicAppBar />
|
||||||
|
|
||||||
|
<v-main>
|
||||||
|
<v-container
|
||||||
|
fluid
|
||||||
|
:class="mobile ? 'pa-2' : 'pa-4'"
|
||||||
|
>
|
||||||
|
<router-view />
|
||||||
|
</v-container>
|
||||||
|
</v-main>
|
||||||
|
</v-app>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useDisplay } from "vuetify"
|
||||||
|
|
||||||
|
import PublicAppBar from "@/components/layout/PublicAppBar.vue"
|
||||||
|
|
||||||
|
const { mobile } = useDisplay()
|
||||||
|
</script>
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="logo">
|
|
||||||
<RouterLink
|
|
||||||
to="/dashboard"
|
|
||||||
class="d-flex"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
class="ml-0 mt-1"
|
|
||||||
style="height: 36px; transform: rotate(-12deg)"
|
|
||||||
:src="AppLogoSmall"
|
|
||||||
/>
|
|
||||||
<div v-if="sidebarMini || mdAndDown"></div>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="d-flex"
|
|
||||||
style="width: 200px"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mt-1 ml-3"
|
|
||||||
style="font-size: 26px; color: #505682"
|
|
||||||
>
|
|
||||||
CALEB BURKE DEV
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</RouterLink>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import AppLogoSmall from "@/assets/app_logo_small.png"
|
|
||||||
|
|
||||||
import { useDisplay } from "vuetify"
|
|
||||||
import useInterface from "@/use/use-interface"
|
|
||||||
import { watch } from "vue"
|
|
||||||
|
|
||||||
const { sidebarMini, setSidebarMini } = useInterface()
|
|
||||||
const { mdAndDown } = useDisplay()
|
|
||||||
|
|
||||||
watch(mdAndDown, (newVal) => {
|
|
||||||
if (newVal === true) setSidebarMini(false)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.logo a {
|
|
||||||
text-decoration: none !important;
|
|
||||||
color: #fff;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<template><div>HOME PAGE</div></template>
|
||||||
@@ -4,10 +4,23 @@ import { authGuard } from "@auth0/auth0-vue"
|
|||||||
import { APPLICATION_NAME } from "@/config"
|
import { APPLICATION_NAME } from "@/config"
|
||||||
import administrationRoutes from "@/routes/administration-routes"
|
import administrationRoutes from "@/routes/administration-routes"
|
||||||
import { authorizationGuard } from "@/utils/authorization-guards"
|
import { authorizationGuard } from "@/utils/authorization-guards"
|
||||||
|
import publicRoutes from "@/routes/public-routes"
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
|
component: () => import("@/layouts/PublicLayout.vue"),
|
||||||
|
meta: { requiresAuth: false },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
name: "HomePage",
|
||||||
|
component: () => import("@/pages/HomePage.vue"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/sign-in",
|
||||||
name: "SignInPage",
|
name: "SignInPage",
|
||||||
component: () => import("@/pages/SignInPage.vue"),
|
component: () => import("@/pages/SignInPage.vue"),
|
||||||
meta: { requiresAuth: false },
|
meta: { requiresAuth: false },
|
||||||
@@ -82,6 +95,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
...publicRoutes,
|
||||||
...administrationRoutes,
|
...administrationRoutes,
|
||||||
{
|
{
|
||||||
name: "StatusPage",
|
name: "StatusPage",
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { RouteRecordRaw } from "vue-router"
|
||||||
|
|
||||||
|
export const publicRoutes: Readonly<RouteRecordRaw[]> = [
|
||||||
|
{
|
||||||
|
path: "/public",
|
||||||
|
component: () => import("@/layouts/PublicLayout.vue"),
|
||||||
|
meta: { requiresAuth: false },
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export default publicRoutes
|
||||||
Reference in New Issue
Block a user