Move job applications to /cv/jobs route and add layout system
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m41s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m41s
- Add DefaultLayout and CVLayout with nested routing - Job applications is now a standalone page at /cv/jobs with a back link - Remove JobApplications embed from CV.vue Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,32 +1,7 @@
|
||||
<script setup>
|
||||
import { RouterView } from "vue-router";
|
||||
import Navbar from "@/components/Navbar.vue";
|
||||
import Footer from "@/components/Footer.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-layout halftone">
|
||||
<Navbar class="no-print sticky top-0 z-50" />
|
||||
<main class="app-content">
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition name="slide" mode="out-in">
|
||||
<component :is="Component" :key="$route.path" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</main>
|
||||
<Footer class="no-print sticky bottom-0 z-50" />
|
||||
</div>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.app-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.app-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
17
vue/src/layouts/CVLayout.vue
Normal file
17
vue/src/layouts/CVLayout.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<script setup>
|
||||
import { RouterView } from "vue-router";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="cv-layout">
|
||||
<RouterView />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.cv-layout {
|
||||
min-height: 100vh;
|
||||
background: white;
|
||||
color: #111;
|
||||
}
|
||||
</style>
|
||||
32
vue/src/layouts/DefaultLayout.vue
Normal file
32
vue/src/layouts/DefaultLayout.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<script setup>
|
||||
import { RouterView } from "vue-router";
|
||||
import Navbar from "@/components/Navbar.vue";
|
||||
import Footer from "@/components/Footer.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="default-layout halftone">
|
||||
<Navbar class="no-print sticky top-0 z-50" />
|
||||
<main class="default-content">
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition name="slide" mode="out-in">
|
||||
<component :is="Component" :key="$route.path" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</main>
|
||||
<Footer class="no-print sticky bottom-0 z-50" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.default-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.default-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,6 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import DefaultLayout from "@/layouts/DefaultLayout.vue";
|
||||
import CVLayout from "@/layouts/CVLayout.vue";
|
||||
import Landing from "@/views/Landing.vue";
|
||||
|
||||
const router = createRouter({
|
||||
@@ -6,63 +8,80 @@ const router = createRouter({
|
||||
routes: [
|
||||
{
|
||||
path: "/",
|
||||
name: "landing",
|
||||
component: Landing,
|
||||
},
|
||||
{
|
||||
path: "/stp",
|
||||
name: "home",
|
||||
component: () => import("@/views/home/Home.vue"),
|
||||
component: DefaultLayout,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "landing",
|
||||
component: Landing,
|
||||
},
|
||||
{
|
||||
path: "stp",
|
||||
name: "home",
|
||||
component: () => import("@/views/home/Home.vue"),
|
||||
},
|
||||
{
|
||||
path: "admin",
|
||||
name: "admin",
|
||||
component: () => import("@/views/admin/Admin.vue"),
|
||||
},
|
||||
{
|
||||
path: "bookmarks",
|
||||
name: "bookmarks",
|
||||
component: () => import("@/views/Bookmarks.vue"),
|
||||
},
|
||||
{
|
||||
path: "notes/:path(.*)*",
|
||||
name: "notes",
|
||||
component: () => import("@/views/Notes.vue"),
|
||||
},
|
||||
{
|
||||
path: "shrines",
|
||||
name: "shrine links",
|
||||
component: () => import("@/views/Shrines.vue"),
|
||||
},
|
||||
{
|
||||
path: "shrines/gto",
|
||||
name: "gto shrine",
|
||||
component: () => import("@/views/shrines/GTO.vue"),
|
||||
},
|
||||
{
|
||||
path: "shrines/skipskipbenben",
|
||||
name: "skipskipbenben shrine",
|
||||
component: () => import("@/views/shrines/Skipskipbenben.vue"),
|
||||
},
|
||||
{
|
||||
path: "shrines/evangelion",
|
||||
name: "evangelion shrine",
|
||||
component: () => import("@/views/shrines/Evangelion.vue"),
|
||||
},
|
||||
{
|
||||
path: "shrines/demoman",
|
||||
name: "demoman shrine",
|
||||
component: () => import("@/views/shrines/Demoman.vue"),
|
||||
},
|
||||
{
|
||||
path: ":pathMatch(.*)*",
|
||||
name: "404",
|
||||
component: () => import("@/views/404.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/cv",
|
||||
name: "cv",
|
||||
component: () => import("../views/CV/CV.vue"),
|
||||
},
|
||||
{
|
||||
path: "/admin",
|
||||
name: "admin",
|
||||
component: () => import("../views/admin/Admin.vue"),
|
||||
},
|
||||
{
|
||||
path: "/bookmarks",
|
||||
name: "bookmarks",
|
||||
component: () => import("../views/Bookmarks.vue"),
|
||||
},
|
||||
{
|
||||
path: "/notes/:path(.*)*",
|
||||
name: "notes",
|
||||
component: () => import("../views/Notes.vue"),
|
||||
},
|
||||
{
|
||||
path: "/shrines",
|
||||
name: "shrine links",
|
||||
component: () => import("../views/Shrines.vue"),
|
||||
},
|
||||
{
|
||||
path: "/shrines/gto",
|
||||
name: "gto shrine",
|
||||
component: () => import("../views/shrines/GTO.vue"),
|
||||
},
|
||||
{
|
||||
path: "/shrines/skipskipbenben",
|
||||
name: "skipskipbenben shrine",
|
||||
component: () => import("../views/shrines/Skipskipbenben.vue"),
|
||||
},
|
||||
{
|
||||
path: "/shrines/evangelion",
|
||||
name: "evangelion shrine",
|
||||
component: () => import("../views/shrines/Evangelion.vue"),
|
||||
},
|
||||
{
|
||||
path: "/shrines/demoman",
|
||||
name: "demoman shrine",
|
||||
component: () => import("../views/shrines/Demoman.vue"),
|
||||
},
|
||||
{
|
||||
path: "/:pathMatch(.*)*",
|
||||
name: "404",
|
||||
component: () => import("../views/404.vue"),
|
||||
component: CVLayout,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "cv",
|
||||
component: () => import("@/views/CV/CV.vue"),
|
||||
},
|
||||
{
|
||||
path: "jobs",
|
||||
name: "job-applications",
|
||||
component: () => import("@/views/CV/JobApplications.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@ import CVGeneral from "./CVGeneral.vue";
|
||||
import CVBackend from "./CVBackend.vue";
|
||||
import CVFrontend from "./CVFrontend.vue";
|
||||
import CVTemp from "./CVTemp.vue";
|
||||
import JobApplications from "./JobApplications.vue";
|
||||
|
||||
const CVHospitality = defineAsyncComponent(() => import("./CVHospitality.vue"));
|
||||
|
||||
@@ -39,7 +38,6 @@ function print() {
|
||||
<Transition name="cv-fade" mode="out-in">
|
||||
<component :is="currentComponent" :key="selected" />
|
||||
</Transition>
|
||||
<JobApplications />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useRouter, RouterLink } from "vue-router";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { gql } from "@/graphql";
|
||||
|
||||
@@ -158,9 +158,12 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="no-print ja-root">
|
||||
<div class="ja-root">
|
||||
<div class="ja-header">
|
||||
<h2 class="ja-heading">Job Applications</h2>
|
||||
<div class="ja-header-left">
|
||||
<RouterLink to="/cv" class="ja-back">← CV</RouterLink>
|
||||
<h2 class="ja-heading">Job Applications</h2>
|
||||
</div>
|
||||
<button class="ja-btn" @click="exportCsv" :disabled="!applications.length">Export CSV</button>
|
||||
</div>
|
||||
|
||||
@@ -259,6 +262,22 @@ onMounted(() => {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.ja-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.ja-back {
|
||||
font-size: 0.85rem;
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ja-back:hover {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.ja-heading {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
|
||||
Reference in New Issue
Block a user