Adding public pages
Build and Push Docker Image / build (push) Successful in 1m8s

This commit is contained in:
2026-07-14 04:07:52 -07:00
parent 1af13091e6
commit b7b473d079
8 changed files with 268 additions and 27 deletions
+126
View File
@@ -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">&#9608;</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>
+66 -27
View File
@@ -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>
+22
View File
@@ -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
View File
@@ -0,0 +1 @@
<template><div>HOME PAGE</div></template>
View File
+14
View File
@@ -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",
+12
View File
@@ -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