-
-
-
-
-
{{ minutesInput }}m
-
-
-
-
{{ secondsInput }}s
-
-
Proceed
-
-
-
Timer finished!
- Reset
-
-
-
Paused
- Reset
-
-
-
- {{ minutes.toString().padStart(2, "0") }}:{{
- seconds.toString().padStart(2, "0")
- }}
-
-
- {{ minutesInput.toString().padStart(2, "0") }}:{{
- secondsInput.toString().padStart(2, "0")
- }}
-
-
Pause
-
+
+
+
+
+
+
{{ minutesInput }}m
+
+
+
+
{{ secondsInput }}s
+
+
Proceed
+
+
Timer finished!
+ Reset
+
+
+
Paused
+ Reset
+
+
+
+ {{ minutes.toString().padStart(2, "0") }}:{{
+ seconds.toString().padStart(2, "0")
+ }}
+
+
+ {{ minutesInput.toString().padStart(2, "0") }}:{{
+ secondsInput.toString().padStart(2, "0")
+ }}
+
+
Pause
+
+
diff --git a/vue/src/components/util/Touchscreen.vue b/vue/src/components/util/Touchscreen.vue
index e7433c7..4c54349 100644
--- a/vue/src/components/util/Touchscreen.vue
+++ b/vue/src/components/util/Touchscreen.vue
@@ -1,15 +1,15 @@
-
-
-
+
+
+
diff --git a/vue/src/components/util/VideoTable.vue b/vue/src/components/util/VideoTable.vue
index 9284cdf..6d99d00 100644
--- a/vue/src/components/util/VideoTable.vue
+++ b/vue/src/components/util/VideoTable.vue
@@ -2,29 +2,29 @@
import { computed } from "vue";
const props = defineProps({
- sourceArr: {
- type: Array,
- required: true,
- },
+ sourceArr: {
+ type: Array,
+ required: true,
+ },
});
function sourceType(link) {
- return "video/" + link.split(".").pop();
+ return "video/" + link.split(".").pop();
}
const keys = ["name", "link"];
-
-
-
+
+
+
diff --git a/vue/src/components/util/Wip.vue b/vue/src/components/util/Wip.vue
index d66e3ef..a975e6f 100644
--- a/vue/src/components/util/Wip.vue
+++ b/vue/src/components/util/Wip.vue
@@ -1,11 +1,11 @@
-
-
-
-
-
Click her, she will take you home
-
-
WIP
-
Sorry for taking you here
-
+
+
+
+
+
Click her, she will take you home
+
+
WIP
+
Sorry for taking you here
+
diff --git a/vue/src/components/util/wasm/AutoScroll.vue b/vue/src/components/util/wasm/AutoScroll.vue
index ea9fd0c..7f7f471 100644
--- a/vue/src/components/util/wasm/AutoScroll.vue
+++ b/vue/src/components/util/wasm/AutoScroll.vue
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/vue/src/graphql.js b/vue/src/graphql.js
index e839b5f..004e6d7 100644
--- a/vue/src/graphql.js
+++ b/vue/src/graphql.js
@@ -2,6 +2,7 @@ import axios from "axios";
export async function gql(query, variables = {}) {
const res = await axios.post("/api/graphql", { query, variables });
- if (res.data.errors && !res.data.data) throw new Error(res.data.errors[0].message);
+ if (res.data.errors && !res.data.data)
+ throw new Error(res.data.errors[0].message);
return res.data.data;
}
diff --git a/vue/src/layouts/CVLayout.vue b/vue/src/layouts/CVLayout.vue
index b085396..7520aba 100644
--- a/vue/src/layouts/CVLayout.vue
+++ b/vue/src/layouts/CVLayout.vue
@@ -3,41 +3,69 @@ import { RouterView } from "vue-router";
-
-
-
+
+
+
diff --git a/vue/src/layouts/DefaultLayout.vue b/vue/src/layouts/DefaultLayout.vue
index 491db42..fd94243 100644
--- a/vue/src/layouts/DefaultLayout.vue
+++ b/vue/src/layouts/DefaultLayout.vue
@@ -5,28 +5,28 @@ import Footer from "@/components/Footer.vue";
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue/src/router/index.js b/vue/src/router/index.js
index 684b5dc..e6097dd 100644
--- a/vue/src/router/index.js
+++ b/vue/src/router/index.js
@@ -7,96 +7,103 @@ import { useHomeDataStore } from "@/stores/homeData";
import { useAuthStore } from "@/stores/auth";
const router = createRouter({
- history: createWebHistory(import.meta.env.BASE_URL),
- routes: [
+ history: createWebHistory(import.meta.env.BASE_URL),
+ routes: [
+ {
+ path: "/",
+ component: DefaultLayout,
+ children: [
{
- path: "/",
- component: DefaultLayout,
- children: [
- {
- path: "",
- name: "landing",
- component: Landing,
- },
- {
- path: "stp",
- name: "home",
- component: () => import("@/views/home/Home.vue"),
- },
- {
- path: "admin/login",
- name: "admin-login",
- component: () => import("@/views/admin/Login.vue"),
- },
- {
- path: "admin",
- name: "admin",
- component: () => import("@/views/admin/Admin.vue"),
- meta: { requiresAdmin: true },
- },
- {
- path: "shrines",
- name: "shrine links",
- component: () => import("@/views/home/shrines/Shrines.vue"),
- },
- {
- path: "shrines/gto",
- name: "gto shrine",
- component: () => import("@/views/home/shrines/GTO.vue"),
- },
- {
- path: "shrines/skipskipbenben",
- name: "skipskipbenben shrine",
- component: () => import("@/views/home/shrines/Skipskipbenben.vue"),
- },
- {
- path: "shrines/evangelion",
- name: "evangelion shrine",
- component: () => import("@/views/home/shrines/Evangelion.vue"),
- },
- {
- path: "shrines/demoman",
- name: "demoman shrine",
- component: () => import("@/views/home/shrines/Demoman.vue"),
- },
- {
- path: ":pathMatch(.*)*",
- name: "404",
- component: () => import("@/views/404/404.vue"),
- },
- ],
+ path: "",
+ name: "landing",
+ component: Landing,
},
{
- path: "/cv",
- component: CVLayout,
- children: [
- {
- path: "",
- name: "cv",
- component: () => import("@/views/CV/CV.vue"),
- },
- {
- path: "jobs",
- name: "job-applications",
- component: () => import("@/views/CV/JobApplications.vue"),
- meta: { requiresAdmin: true },
- },
- ],
+ path: "stp",
+ name: "home",
+ component: () => import("@/views/home/Home.vue"),
},
- ],
+ {
+ path: "admin/login",
+ name: "admin-login",
+ component: () => import("@/views/admin/Login.vue"),
+ },
+ {
+ path: "admin",
+ name: "admin",
+ component: () => import("@/views/admin/Admin.vue"),
+ meta: { requiresAdmin: true },
+ },
+ {
+ path: "shrines",
+ name: "shrine links",
+ component: () => import("@/views/home/shrines/Shrines.vue"),
+ },
+ {
+ path: "shrines/gto",
+ name: "gto shrine",
+ component: () => import("@/views/home/shrines/GTO.vue"),
+ },
+ {
+ path: "shrines/skipskipbenben",
+ name: "skipskipbenben shrine",
+ component: () => import("@/views/home/shrines/Skipskipbenben.vue"),
+ },
+ {
+ path: "shrines/evangelion",
+ name: "evangelion shrine",
+ component: () => import("@/views/home/shrines/Evangelion.vue"),
+ },
+ {
+ path: "shrines/demoman",
+ name: "demoman shrine",
+ component: () => import("@/views/home/shrines/Demoman.vue"),
+ },
+ {
+ path: ":pathMatch(.*)*",
+ name: "404",
+ component: () => import("@/views/404/404.vue"),
+ },
+ ],
+ },
+ {
+ path: "/cv",
+ component: CVLayout,
+ children: [
+ {
+ path: "",
+ name: "cv",
+ component: () => import("@/views/CV/CV.vue"),
+ },
+ {
+ path: "jobs",
+ name: "job-applications",
+ component: () => import("@/views/CV/JobApplications.vue"),
+ meta: { requiresAdmin: true },
+ },
+ ],
+ },
+ ],
});
router.beforeEach(async (to) => {
- if (!to.meta.requiresAdmin) return;
- const homeData = useHomeDataStore();
- if (!homeData.loaded) {
- await new Promise((resolve) => {
- const stop = watch(() => homeData.loaded, (val) => {
- if (val) { stop(); resolve(); }
- });
- });
- }
- if (!useAuthStore().user.admin) return { path: "/admin/login", query: { redirect: to.fullPath } };
+ if (!to.meta.requiresAdmin) return;
+ const homeData = useHomeDataStore();
+ if (!homeData.loaded) {
+ await new Promise((resolve) => {
+ const stop = watch(
+ () => homeData.loaded,
+ (val) => {
+ if (val) {
+ stop();
+ resolve();
+ }
+ },
+ );
+ });
+ }
+ if (!useAuthStore().user.admin)
+ return { path: "/admin/login", query: { redirect: to.fullPath } };
});
export default router;
diff --git a/vue/src/views/404/404.vue b/vue/src/views/404/404.vue
index 46d22a2..3055b3b 100644
--- a/vue/src/views/404/404.vue
+++ b/vue/src/views/404/404.vue
@@ -1,13 +1,13 @@
-
-
-
404
-
-
-
-
Click her, she will take you home
-
-
+
+
+
404
+
+
+
+
Click her, she will take you home
+
+
diff --git a/vue/src/views/CV/JobApplications.vue b/vue/src/views/CV/JobApplications.vue
index 706423d..1937ab3 100644
--- a/vue/src/views/CV/JobApplications.vue
+++ b/vue/src/views/CV/JobApplications.vue
@@ -7,13 +7,13 @@ const applications = ref([]);
const editingId = ref(null);
const editForm = ref({});
const form = ref({
- jobTitle: "",
- company: "",
- location: "",
- url: "",
- status: "Applied",
- notes: "",
- appliedAt: "",
+ jobTitle: "",
+ company: "",
+ location: "",
+ url: "",
+ status: "Applied",
+ notes: "",
+ appliedAt: "",
});
const references = ref([]);
@@ -23,598 +23,782 @@ const editRefForm = ref({});
const REF_CATEGORIES = ["profile", "experience"];
const REF_FIELDS = `id category label value sortOrder createdAt`;
-const STATUS_OPTIONS = ["Applied", "Screening", "Interview", "Offer", "Rejected", "Withdrawn"];
+const STATUS_OPTIONS = [
+ "Applied",
+ "Screening",
+ "Interview",
+ "Offer",
+ "Rejected",
+ "Withdrawn",
+];
const APP_FIELDS = `id jobTitle company location url status notes appliedAt createdAt`;
async function fetchApplications() {
- try {
- const data = await gql(`query { jobApplications { ${APP_FIELDS} } }`);
- applications.value = data.jobApplications;
- } catch (err) {
- console.error(err);
- }
+ try {
+ const data = await gql(`query { jobApplications { ${APP_FIELDS} } }`);
+ applications.value = data.jobApplications;
+ } catch (err) {
+ console.error(err);
+ }
}
async function createApplication() {
- if (!form.value.jobTitle || !form.value.company || !form.value.status) return;
- try {
- const input = {
- jobTitle: form.value.jobTitle,
- company: form.value.company,
- status: form.value.status,
- location: form.value.location || undefined,
- url: form.value.url || undefined,
- notes: form.value.notes || undefined,
- appliedAt: form.value.appliedAt ? new Date(form.value.appliedAt).toISOString() : undefined,
- };
- const data = await gql(
- `mutation CreateJobApplication($input: CreateJobApplicationInput!) {
+ if (!form.value.jobTitle || !form.value.company || !form.value.status) return;
+ try {
+ const input = {
+ jobTitle: form.value.jobTitle,
+ company: form.value.company,
+ status: form.value.status,
+ location: form.value.location || undefined,
+ url: form.value.url || undefined,
+ notes: form.value.notes || undefined,
+ appliedAt: form.value.appliedAt
+ ? new Date(form.value.appliedAt).toISOString()
+ : undefined,
+ };
+ const data = await gql(
+ `mutation CreateJobApplication($input: CreateJobApplicationInput!) {
createJobApplication(input: $input) { ${APP_FIELDS} }
}`,
- { input },
- );
- applications.value.unshift(data.createJobApplication);
- form.value = { jobTitle: "", company: "", location: "", url: "", status: "Applied", notes: "", appliedAt: "" };
- } catch (err) {
- console.error(err);
- }
+ { input },
+ );
+ applications.value.unshift(data.createJobApplication);
+ form.value = {
+ jobTitle: "",
+ company: "",
+ location: "",
+ url: "",
+ status: "Applied",
+ notes: "",
+ appliedAt: "",
+ };
+ } catch (err) {
+ console.error(err);
+ }
}
function startEdit(app) {
- editingId.value = app.id;
- editForm.value = {
- jobTitle: app.jobTitle,
- company: app.company,
- location: app.location ?? "",
- url: app.url ?? "",
- status: app.status,
- notes: app.notes ?? "",
- appliedAt: app.appliedAt ? app.appliedAt.substring(0, 10) : "",
- };
+ editingId.value = app.id;
+ editForm.value = {
+ jobTitle: app.jobTitle,
+ company: app.company,
+ location: app.location ?? "",
+ url: app.url ?? "",
+ status: app.status,
+ notes: app.notes ?? "",
+ appliedAt: app.appliedAt ? app.appliedAt.substring(0, 10) : "",
+ };
}
function cancelEdit() {
- editingId.value = null;
- editForm.value = {};
+ editingId.value = null;
+ editForm.value = {};
}
async function saveEdit(id) {
- try {
- const input = {
- jobTitle: editForm.value.jobTitle || undefined,
- company: editForm.value.company || undefined,
- status: editForm.value.status || undefined,
- location: editForm.value.location || undefined,
- url: editForm.value.url || undefined,
- notes: editForm.value.notes || undefined,
- appliedAt: editForm.value.appliedAt ? new Date(editForm.value.appliedAt).toISOString() : undefined,
- };
- const data = await gql(
- `mutation UpdateJobApplication($id: ID!, $input: UpdateJobApplicationInput!) {
+ try {
+ const input = {
+ jobTitle: editForm.value.jobTitle || undefined,
+ company: editForm.value.company || undefined,
+ status: editForm.value.status || undefined,
+ location: editForm.value.location || undefined,
+ url: editForm.value.url || undefined,
+ notes: editForm.value.notes || undefined,
+ appliedAt: editForm.value.appliedAt
+ ? new Date(editForm.value.appliedAt).toISOString()
+ : undefined,
+ };
+ const data = await gql(
+ `mutation UpdateJobApplication($id: ID!, $input: UpdateJobApplicationInput!) {
updateJobApplication(id: $id, input: $input) { ${APP_FIELDS} }
}`,
- { id, input },
- );
- const idx = applications.value.findIndex((a) => a.id === id);
- if (idx !== -1) applications.value[idx] = data.updateJobApplication;
- editingId.value = null;
- } catch (err) {
- console.error(err);
- }
+ { id, input },
+ );
+ const idx = applications.value.findIndex((a) => a.id === id);
+ if (idx !== -1) applications.value[idx] = data.updateJobApplication;
+ editingId.value = null;
+ } catch (err) {
+ console.error(err);
+ }
}
async function deleteApplication(id) {
- try {
- await gql(
- `mutation DeleteJobApplication($id: ID!) { deleteJobApplication(id: $id) }`,
- { id },
- );
- applications.value = applications.value.filter((a) => a.id !== id);
- } catch (err) {
- console.error(err);
- }
+ try {
+ await gql(
+ `mutation DeleteJobApplication($id: ID!) { deleteJobApplication(id: $id) }`,
+ { id },
+ );
+ applications.value = applications.value.filter((a) => a.id !== id);
+ } catch (err) {
+ console.error(err);
+ }
}
function exportCsv() {
- const headers = ["Job Title", "Company", "Status", "Location", "URL", "Applied", "Notes", "Created"];
- const rows = applications.value.map((a) => [
- a.jobTitle,
- a.company,
- a.status,
- a.location ?? "",
- a.url ?? "",
- a.appliedAt ? a.appliedAt.substring(0, 10) : "",
- a.notes ?? "",
- a.createdAt ? a.createdAt.substring(0, 10) : "",
- ]);
- const escape = (v) => `"${String(v).replace(/"/g, '""')}"`;
- const csv = [headers, ...rows].map((r) => r.map(escape).join(",")).join("\n");
- const blob = new Blob([csv], { type: "text/csv" });
- const url = URL.createObjectURL(blob);
- const a = document.createElement("a");
- a.href = url;
- a.download = "job_applications.csv";
- a.click();
- URL.revokeObjectURL(url);
+ const headers = [
+ "Job Title",
+ "Company",
+ "Status",
+ "Location",
+ "URL",
+ "Applied",
+ "Notes",
+ "Created",
+ ];
+ const rows = applications.value.map((a) => [
+ a.jobTitle,
+ a.company,
+ a.status,
+ a.location ?? "",
+ a.url ?? "",
+ a.appliedAt ? a.appliedAt.substring(0, 10) : "",
+ a.notes ?? "",
+ a.createdAt ? a.createdAt.substring(0, 10) : "",
+ ]);
+ const escape = (v) => `"${String(v).replace(/"/g, '""')}"`;
+ const csv = [headers, ...rows].map((r) => r.map(escape).join(",")).join("\n");
+ const blob = new Blob([csv], { type: "text/csv" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = "job_applications.csv";
+ a.click();
+ URL.revokeObjectURL(url);
}
async function fetchReferences() {
- try {
- const data = await gql(`query { jobAppReferences { ${REF_FIELDS} } }`);
- references.value = data.jobAppReferences;
- } catch (err) {
- console.error(err);
- }
+ try {
+ const data = await gql(`query { jobAppReferences { ${REF_FIELDS} } }`);
+ references.value = data.jobAppReferences;
+ } catch (err) {
+ console.error(err);
+ }
}
async function createReference() {
- if (!refForm.value.label || !refForm.value.value) return;
- try {
- const input = {
- category: refForm.value.category,
- label: refForm.value.label,
- value: refForm.value.value,
- };
- const data = await gql(
- `mutation CreateJobAppReference($input: CreateJobAppReferenceInput!) {
+ if (!refForm.value.label || !refForm.value.value) return;
+ try {
+ const input = {
+ category: refForm.value.category,
+ label: refForm.value.label,
+ value: refForm.value.value,
+ };
+ const data = await gql(
+ `mutation CreateJobAppReference($input: CreateJobAppReferenceInput!) {
createJobAppReference(input: $input) { ${REF_FIELDS} }
}`,
- { input },
- );
- references.value.push(data.createJobAppReference);
- refForm.value = { category: refForm.value.category, label: "", value: "" };
- } catch (err) {
- console.error(err);
- }
+ { input },
+ );
+ references.value.push(data.createJobAppReference);
+ refForm.value = { category: refForm.value.category, label: "", value: "" };
+ } catch (err) {
+ console.error(err);
+ }
}
function startRefEdit(ref) {
- editingRefId.value = ref.id;
- editRefForm.value = { category: ref.category, label: ref.label, value: ref.value };
+ editingRefId.value = ref.id;
+ editRefForm.value = {
+ category: ref.category,
+ label: ref.label,
+ value: ref.value,
+ };
}
function cancelRefEdit() {
- editingRefId.value = null;
- editRefForm.value = {};
+ editingRefId.value = null;
+ editRefForm.value = {};
}
async function saveRefEdit(id) {
- try {
- const input = {
- category: editRefForm.value.category || undefined,
- label: editRefForm.value.label || undefined,
- value: editRefForm.value.value || undefined,
- };
- const data = await gql(
- `mutation UpdateJobAppReference($id: ID!, $input: UpdateJobAppReferenceInput!) {
+ try {
+ const input = {
+ category: editRefForm.value.category || undefined,
+ label: editRefForm.value.label || undefined,
+ value: editRefForm.value.value || undefined,
+ };
+ const data = await gql(
+ `mutation UpdateJobAppReference($id: ID!, $input: UpdateJobAppReferenceInput!) {
updateJobAppReference(id: $id, input: $input) { ${REF_FIELDS} }
}`,
- { id, input },
- );
- const idx = references.value.findIndex((r) => r.id === id);
- if (idx !== -1) references.value[idx] = data.updateJobAppReference;
- editingRefId.value = null;
- } catch (err) {
- console.error(err);
- }
+ { id, input },
+ );
+ const idx = references.value.findIndex((r) => r.id === id);
+ if (idx !== -1) references.value[idx] = data.updateJobAppReference;
+ editingRefId.value = null;
+ } catch (err) {
+ console.error(err);
+ }
}
async function deleteReference(id) {
- try {
- await gql(
- `mutation DeleteJobAppReference($id: ID!) { deleteJobAppReference(id: $id) }`,
- { id },
- );
- references.value = references.value.filter((r) => r.id !== id);
- } catch (err) {
- console.error(err);
- }
+ try {
+ await gql(
+ `mutation DeleteJobAppReference($id: ID!) { deleteJobAppReference(id: $id) }`,
+ { id },
+ );
+ references.value = references.value.filter((r) => r.id !== id);
+ } catch (err) {
+ console.error(err);
+ }
}
function refsByCategory(category) {
- return references.value.filter((r) => r.category === category);
+ return references.value.filter((r) => r.category === category);
}
function copyToClipboard(text) {
- navigator.clipboard.writeText(text);
+ navigator.clipboard.writeText(text);
}
function statusClass(status) {
- const map = {
- Applied: "status-applied",
- Screening: "status-screening",
- Interview: "status-interview",
- Offer: "status-offer",
- Rejected: "status-rejected",
- Withdrawn: "status-withdrawn",
- };
- return map[status] ?? "";
+ const map = {
+ Applied: "status-applied",
+ Screening: "status-screening",
+ Interview: "status-interview",
+ Offer: "status-offer",
+ Rejected: "status-rejected",
+ Withdrawn: "status-withdrawn",
+ };
+ return map[status] ?? "";
}
onMounted(() => {
- fetchApplications();
- fetchReferences();
+ fetchApplications();
+ fetchReferences();
});
-
-
-
-
-
Quick Reference
-
-
{{ cat }}
-
-
- {{ ref.label }}
- {{ ref.value }}
- Copy
- Edit
- Delete
-
-
-
- {{ c }}
-
-
-
- Save
- Cancel
-
-
-
No {{ cat }} items yet.
-
-
-
-
-
-
-
-
No applications yet.
+
diff --git a/vue/src/views/CV/Project.vue b/vue/src/views/CV/Project.vue
index 2378b96..05e4400 100644
--- a/vue/src/views/CV/Project.vue
+++ b/vue/src/views/CV/Project.vue
@@ -1,17 +1,17 @@
-
-
-
-
-
+
diff --git a/vue/src/views/admin/Admin.vue b/vue/src/views/admin/Admin.vue
index 199a72d..449e5a1 100644
--- a/vue/src/views/admin/Admin.vue
+++ b/vue/src/views/admin/Admin.vue
@@ -9,15 +9,15 @@ import ManageRadio from "./ManageRadio.vue";
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue/src/views/admin/CreateActivity.vue b/vue/src/views/admin/CreateActivity.vue
index ac73e55..efcf2ff 100644
--- a/vue/src/views/admin/CreateActivity.vue
+++ b/vue/src/views/admin/CreateActivity.vue
@@ -11,29 +11,35 @@ const name = ref("");
const link = ref("");
async function post() {
- try {
- const data = await gql(
- `mutation CreateActivity($input: CreateActivityInput!) { createActivity(input: $input) { id } }`,
- { input: { type: type.value, name: name.value, link: link.value || undefined } },
- );
- type.value = "";
- name.value = "";
- link.value = "";
- console.log(data.createActivity);
- emit("done");
- } catch (err) {
- console.error(err);
- }
+ try {
+ const data = await gql(
+ `mutation CreateActivity($input: CreateActivityInput!) { createActivity(input: $input) { id } }`,
+ {
+ input: {
+ type: type.value,
+ name: name.value,
+ link: link.value || undefined,
+ },
+ },
+ );
+ type.value = "";
+ name.value = "";
+ link.value = "";
+ console.log(data.createActivity);
+ emit("done");
+ } catch (err) {
+ console.error(err);
+ }
}
-
-
Create Activity
-
-
-
- Upload
- Cancel
-
+
+
Create Activity
+
+
+
+ Upload
+ Cancel
+
diff --git a/vue/src/views/admin/CreateBookmark.vue b/vue/src/views/admin/CreateBookmark.vue
index 08dcdd1..0e2b236 100644
--- a/vue/src/views/admin/CreateBookmark.vue
+++ b/vue/src/views/admin/CreateBookmark.vue
@@ -10,28 +10,40 @@ const name = ref("");
const link = ref("");
async function submit() {
- try {
- await gql(
- `mutation CreateBookmark($input: CreateBookmarkInput!) { createBookmark(input: $input) { id } }`,
- { input: { category: category.value, name: name.value, link: link.value } },
- );
- category.value = "";
- name.value = "";
- link.value = "";
- emit("done");
- } catch (err) {
- console.error(err);
- }
+ try {
+ await gql(
+ `mutation CreateBookmark($input: CreateBookmarkInput!) { createBookmark(input: $input) { id } }`,
+ {
+ input: { category: category.value, name: name.value, link: link.value },
+ },
+ );
+ category.value = "";
+ name.value = "";
+ link.value = "";
+ emit("done");
+ } catch (err) {
+ console.error(err);
+ }
}
-
-
Create Bookmark
-
-
-
- Upload
- Cancel
-
+
+
Create Bookmark
+
+
+
+ Upload
+ Cancel
+
diff --git a/vue/src/views/admin/CreateFavorite.vue b/vue/src/views/admin/CreateFavorite.vue
index 6493d01..e366832 100644
--- a/vue/src/views/admin/CreateFavorite.vue
+++ b/vue/src/views/admin/CreateFavorite.vue
@@ -11,29 +11,35 @@ const name = ref("");
const link = ref("");
async function post() {
- try {
- const data = await gql(
- `mutation CreateFavorite($input: CreateFavoriteInput!) { createFavorite(input: $input) { id } }`,
- { input: { type: type.value, name: name.value, link: link.value || undefined } },
- );
- type.value = "";
- name.value = "";
- link.value = "";
- console.log(data.createFavorite);
- emit("done");
- } catch (err) {
- console.error(err);
- }
+ try {
+ const data = await gql(
+ `mutation CreateFavorite($input: CreateFavoriteInput!) { createFavorite(input: $input) { id } }`,
+ {
+ input: {
+ type: type.value,
+ name: name.value,
+ link: link.value || undefined,
+ },
+ },
+ );
+ type.value = "";
+ name.value = "";
+ link.value = "";
+ console.log(data.createFavorite);
+ emit("done");
+ } catch (err) {
+ console.error(err);
+ }
}
-
-
Create Favorite
-
-
-
- Upload
- Cancel
-
+
+
Create Favorite
+
+
+
+ Upload
+ Cancel
+
diff --git a/vue/src/views/admin/CreatePost.vue b/vue/src/views/admin/CreatePost.vue
index 5722273..0574e92 100644
--- a/vue/src/views/admin/CreatePost.vue
+++ b/vue/src/views/admin/CreatePost.vue
@@ -9,31 +9,32 @@ const title = ref("");
const content = ref("");
async function post() {
- try {
- const data = await gql(
- `mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { id } }`,
- { input: { title: title.value, content: content.value } },
- );
- title.value = "";
- content.value = "";
- console.log(data.createPost);
- emit("done");
- } catch (err) {
- console.error(err);
- }
+ try {
+ const data = await gql(
+ `mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { id } }`,
+ { input: { title: title.value, content: content.value } },
+ );
+ title.value = "";
+ content.value = "";
+ console.log(data.createPost);
+ emit("done");
+ } catch (err) {
+ console.error(err);
+ }
}
-
-
Create Post
-
-
- Upload
- Cancel
-
+
+
Create Post
+
+
+ Upload
+ Cancel
+
diff --git a/vue/src/views/admin/CreateRowing.vue b/vue/src/views/admin/CreateRowing.vue
index 4f92b9a..cd0de42 100644
--- a/vue/src/views/admin/CreateRowing.vue
+++ b/vue/src/views/admin/CreateRowing.vue
@@ -9,47 +9,60 @@ const images = ref([]);
const results = ref([]);
function onFileChange(e) {
- images.value = Array.from(e.target.files);
- results.value = [];
+ images.value = Array.from(e.target.files);
+ results.value = [];
}
async function submit() {
- if (!images.value.length) return;
- results.value = images.value.map((f) => ({ name: f.name, status: "Uploading..." }));
+ if (!images.value.length) return;
+ results.value = images.value.map((f) => ({
+ name: f.name,
+ status: "Uploading...",
+ }));
- await Promise.all(
- images.value.map(async (file, i) => {
- const formData = new FormData();
- formData.append("image", file);
- try {
- const res = await axios.post("/api/rowing", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
- const mins = Math.floor(res.data.Time / 1e9 / 60);
- const secs = String(Math.floor((res.data.Time / 1e9) % 60)).padStart(2, "0");
- results.value[i].status = `${res.data.Distance}m in ${mins}:${secs}`;
- results.value[i].ok = true;
- } catch (err) {
- results.value[i].status = err.response?.data?.error || "Upload failed";
- results.value[i].ok = false;
- }
- })
- );
+ await Promise.all(
+ images.value.map(async (file, i) => {
+ const formData = new FormData();
+ formData.append("image", file);
+ try {
+ const res = await axios.post("/api/rowing", formData, {
+ headers: { "Content-Type": "multipart/form-data" },
+ });
+ const mins = Math.floor(res.data.Time / 1e9 / 60);
+ const secs = String(Math.floor((res.data.Time / 1e9) % 60)).padStart(
+ 2,
+ "0",
+ );
+ results.value[i].status = `${res.data.Distance}m in ${mins}:${secs}`;
+ results.value[i].ok = true;
+ } catch (err) {
+ results.value[i].status = err.response?.data?.error || "Upload failed";
+ results.value[i].ok = false;
+ }
+ }),
+ );
- images.value = [];
- emit("done");
+ images.value = [];
+ emit("done");
}
-
-
Create Rowing
-
-
Upload
-
Cancel
-
- {{ r.name }}:
- {{ r.status }}
-
+
+
Create Rowing
+
+
Upload
+
Cancel
+
+ {{ r.name }}:
+ {{
+ r.status
+ }}
+
diff --git a/vue/src/views/admin/CreateUser.vue b/vue/src/views/admin/CreateUser.vue
index 02b2c3f..4d080ef 100644
--- a/vue/src/views/admin/CreateUser.vue
+++ b/vue/src/views/admin/CreateUser.vue
@@ -11,35 +11,45 @@ const message = ref("");
const error = ref("");
async function handleCreate() {
- message.value = "";
- error.value = "";
- try {
- const data = await gql(
- `mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id username } }`,
- { input: { username: username.value, password: password.value } },
- );
- message.value = `User "${data.createUser.username}" created successfully.`;
- username.value = "";
- password.value = "";
- } catch (err) {
- error.value = err.message || "Failed to create user.";
- }
+ message.value = "";
+ error.value = "";
+ try {
+ const data = await gql(
+ `mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id username } }`,
+ { input: { username: username.value, password: password.value } },
+ );
+ message.value = `User "${data.createUser.username}" created successfully.`;
+ username.value = "";
+ password.value = "";
+ } catch (err) {
+ error.value = err.message || "Failed to create user.";
+ }
}
-
-
Create User
-
{{ message }}
-
{{ error }}
-
-
-
Create Account
-
-
-
You do not have permission to create users.
-
-
-
You must be logged in as an admin to create users.
-
+
+
Create User
+
{{ message }}
+
{{ error }}
+
+
+
Create Account
+
+
+
You do not have permission to create users.
+
+
+
You must be logged in as an admin to create users.
+
diff --git a/vue/src/views/admin/Login.vue b/vue/src/views/admin/Login.vue
index dc9039f..0747cb0 100644
--- a/vue/src/views/admin/Login.vue
+++ b/vue/src/views/admin/Login.vue
@@ -12,29 +12,39 @@ const username = ref("");
const password = ref("");
async function handleLogin() {
- await auth.logIn(username.value, password.value);
- if (auth.loggedIn && route.query.redirect) {
- router.push(route.query.redirect);
- }
+ await auth.logIn(username.value, password.value);
+ if (auth.loggedIn && route.query.redirect) {
+ router.push(route.query.redirect);
+ }
}
function handleLogout() {
- auth.logOut();
+ auth.logOut();
}
-
-
Logged in
-
{{ auth.user.id }}
-
{{ auth.user.username }}
-
{{ auth.user.admin }}
-
Log Out
-
-
-
Login
-
-
- Log In
-
+
+
Logged in
+
{{ auth.user.id }}
+
{{ auth.user.username }}
+
{{ auth.user.admin }}
+
Log Out
+
+
+
Login
+
+
+ Log In
+
diff --git a/vue/src/views/admin/ManageRadio.vue b/vue/src/views/admin/ManageRadio.vue
index 27a4148..127ec8f 100644
--- a/vue/src/views/admin/ManageRadio.vue
+++ b/vue/src/views/admin/ManageRadio.vue
@@ -9,94 +9,108 @@ const results = ref([]);
const loading = ref(false);
async function fetchSongs() {
- try {
- const res = await axios.get("/api/radio/songs");
- songs.value = res.data.songs;
- } catch (err) {
- console.error(err);
- }
+ try {
+ const res = await axios.get("/api/radio/songs");
+ songs.value = res.data.songs;
+ } catch (err) {
+ console.error(err);
+ }
}
function onFileChange(e) {
- files.value = Array.from(e.target.files);
- results.value = [];
+ files.value = Array.from(e.target.files);
+ results.value = [];
}
async function upload() {
- if (!files.value.length) return;
- loading.value = true;
- results.value = files.value.map((f) => ({ name: f.name, status: "Uploading..." }));
+ if (!files.value.length) return;
+ loading.value = true;
+ results.value = files.value.map((f) => ({
+ name: f.name,
+ status: "Uploading...",
+ }));
- await Promise.all(
- files.value.map(async (file, i) => {
- const formData = new FormData();
- formData.append("file", file);
- try {
- await axios.post("/api/radio/upload", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
- results.value[i].status = "Uploaded";
- results.value[i].ok = true;
- } catch (err) {
- results.value[i].status = err.response?.data?.error || "Upload failed";
- results.value[i].ok = false;
- }
- })
- );
+ await Promise.all(
+ files.value.map(async (file, i) => {
+ const formData = new FormData();
+ formData.append("file", file);
+ try {
+ await axios.post("/api/radio/upload", formData, {
+ headers: { "Content-Type": "multipart/form-data" },
+ });
+ results.value[i].status = "Uploaded";
+ results.value[i].ok = true;
+ } catch (err) {
+ results.value[i].status = err.response?.data?.error || "Upload failed";
+ results.value[i].ok = false;
+ }
+ }),
+ );
- files.value = [];
- loading.value = false;
- await fetchSongs();
+ files.value = [];
+ loading.value = false;
+ await fetchSongs();
}
async function deleteSong(name) {
- try {
- await axios.delete(`/api/radio/songs/${encodeURIComponent(name)}`);
- await fetchSongs();
- } catch (err) {
- console.error(err);
- }
+ try {
+ await axios.delete(`/api/radio/songs/${encodeURIComponent(name)}`);
+ await fetchSongs();
+ } catch (err) {
+ console.error(err);
+ }
}
async function toggleSong(song) {
- const action = song.disabled ? "enable" : "disable";
- try {
- await axios.patch(`/api/radio/songs/${encodeURIComponent(song.name)}/${action}`);
- await fetchSongs();
- } catch (err) {
- console.error(err);
- }
+ const action = song.disabled ? "enable" : "disable";
+ try {
+ await axios.patch(
+ `/api/radio/songs/${encodeURIComponent(song.name)}/${action}`,
+ );
+ await fetchSongs();
+ } catch (err) {
+ console.error(err);
+ }
}
function formatSize(bytes) {
- if (bytes < 1024) return bytes + " B";
- if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
- return (bytes / (1024 * 1024)).toFixed(1) + " MB";
+ if (bytes < 1024) return bytes + " B";
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
+ return (bytes / (1024 * 1024)).toFixed(1) + " MB";
}
onMounted(fetchSongs);
-
-
Manage Radio
-
-
Upload
-
- {{ r.name }}:
- {{ r.status }}
-
-
- {{ song.name }}
- {{ formatSize(song.size) }}
- disabled
- {{ song.disabled ? "Enable" : "Disable" }}
- Delete
-
+
+
Manage Radio
+
+
Upload
+
+ {{ r.name }}:
+ {{
+ r.status
+ }}
+
+ {{ song.name }}
+ {{ formatSize(song.size) }}
+ disabled
+ {{
+ song.disabled ? "Enable" : "Disable"
+ }}
+ Delete
+
+
diff --git a/vue/src/views/admin/ManageUsers.vue b/vue/src/views/admin/ManageUsers.vue
index d24d042..e2804cd 100644
--- a/vue/src/views/admin/ManageUsers.vue
+++ b/vue/src/views/admin/ManageUsers.vue
@@ -8,38 +8,39 @@ const auth = useAuthStore();
const users = ref([]);
async function fetchUsers() {
- try {
- const data = await gql(`query { users { id username admin } }`);
- users.value = data.users;
- } catch (err) {
- console.error(err);
- }
+ try {
+ const data = await gql(`query { users { id username admin } }`);
+ users.value = data.users;
+ } catch (err) {
+ console.error(err);
+ }
}
async function toggleAdmin(user) {
- try {
- const data = await auth.setUserAdmin(user.id, !user.admin);
- user.admin = data.admin;
- } catch (err) {
- console.error(err);
- }
+ try {
+ const data = await auth.setUserAdmin(user.id, !user.admin);
+ user.admin = data.admin;
+ } catch (err) {
+ console.error(err);
+ }
}
onMounted(fetchUsers);
-
-
Manage Users
-
- {{ user.username }}
- (admin)
-
- {{ user.admin ? "Demote" : "Promote" }}
-
-
+
+
Manage Users
+
+ {{ user.username }}
+ (admin)
+
+ {{ user.admin ? "Demote" : "Promote" }}
+
+
diff --git a/vue/src/views/home/BadApple.vue b/vue/src/views/home/BadApple.vue
index a3228c7..7bc350a 100644
--- a/vue/src/views/home/BadApple.vue
+++ b/vue/src/views/home/BadApple.vue
@@ -1,7 +1,7 @@
- {{ displayText
- }}
+ {{ displayText }}
diff --git a/vue/src/views/home/Bookmarks.vue b/vue/src/views/home/Bookmarks.vue
index 44c91c6..b72ff0d 100644
--- a/vue/src/views/home/Bookmarks.vue
+++ b/vue/src/views/home/Bookmarks.vue
@@ -5,7 +5,9 @@ import Header from "@/components/text/Header.vue";
import { useHomeDataStore } from "@/stores/homeData";
import { useAuthStore } from "@/stores/auth";
-const CreateBookmark = defineAsyncComponent(() => import("@/views/admin/CreateBookmark.vue"));
+const CreateBookmark = defineAsyncComponent(
+ () => import("@/views/admin/CreateBookmark.vue"),
+);
const homeData = useHomeDataStore();
const authStore = useAuthStore();
@@ -13,48 +15,57 @@ const authStore = useAuthStore();
const showCreate = ref(false);
const groupedBookmarks = computed(() => {
- const groups = {};
- for (const b of homeData.bookmarks) {
- if (!groups[b.category]) groups[b.category] = [];
- groups[b.category].push(b);
- }
- return Object.entries(groups);
+ const groups = {};
+ for (const b of homeData.bookmarks) {
+ if (!groups[b.category]) groups[b.category] = [];
+ groups[b.category].push(b);
+ }
+ return Object.entries(groups);
});
-
-
-
- {{ showCreate ? "Create Bookmark" : "Bookmarks" }}
-
- {{ showCreate ? "x" : "+" }}
-
-
-
-
-
-
-
+
+
+
+ {{ showCreate ? "Create Bookmark" : "Bookmarks" }}
+
+ {{ showCreate ? "x" : "+" }}
+
+
+
+
+
+
+
diff --git a/vue/src/views/home/Collage.vue b/vue/src/views/home/Collage.vue
index b4d3633..b2b2c33 100644
--- a/vue/src/views/home/Collage.vue
+++ b/vue/src/views/home/Collage.vue
@@ -2,14 +2,14 @@
import Slideshow from "@/components/util/Slideshow.vue";
const images = [
- { url: "/img/memes/pidgeon.gif", comment: "鸟" },
- // { url: "/img/memes/no_slip.png" },
- // { url: "/img/memes/epic.jpeg" },
- // { url: "/img/bedroom/img2.png", comment: "办公桌" },
- // { url: "/img/bedroom/img1.png", comment: "床" },
+ { url: "/img/memes/pidgeon.gif", comment: "鸟" },
+ // { url: "/img/memes/no_slip.png" },
+ // { url: "/img/memes/epic.jpeg" },
+ // { url: "/img/bedroom/img2.png", comment: "办公桌" },
+ // { url: "/img/bedroom/img1.png", comment: "床" },
];
-
+
diff --git a/vue/src/views/home/Consumption.vue b/vue/src/views/home/Consumption.vue
index 25a7f7a..01b6997 100644
--- a/vue/src/views/home/Consumption.vue
+++ b/vue/src/views/home/Consumption.vue
@@ -7,7 +7,9 @@ import { ref, defineAsyncComponent } from "vue";
import { useActivityStore } from "@/stores/activity";
import { useAuthStore } from "@/stores/auth";
-const CreateActivity = defineAsyncComponent(() => import("@/views/admin/CreateActivity.vue"));
+const CreateActivity = defineAsyncComponent(
+ () => import("@/views/admin/CreateActivity.vue"),
+);
const activityStore = useActivityStore();
const authStore = useAuthStore();
@@ -15,18 +17,31 @@ const showCreate = ref(false);
-
-
-
- {{ showCreate ? "Create Activity" : "Consumption" }}
-
- {{ showCreate ? "x" : "+" }}
-
-
-
-
-
-
-
-
+
+
+
+ {{ showCreate ? "Create Activity" : "Consumption" }}
+
+ {{ showCreate ? "x" : "+" }}
+
+
+
+
+
+
+
+
diff --git a/vue/src/views/home/Favorites.vue b/vue/src/views/home/Favorites.vue
index 8d6e23c..9d75d2d 100644
--- a/vue/src/views/home/Favorites.vue
+++ b/vue/src/views/home/Favorites.vue
@@ -7,7 +7,9 @@ import { ref, defineAsyncComponent } from "vue";
import { useFavoritesStore } from "@/stores/favorites";
import { useAuthStore } from "@/stores/auth";
-const CreateFavorite = defineAsyncComponent(() => import("@/views/admin/CreateFavorite.vue"));
+const CreateFavorite = defineAsyncComponent(
+ () => import("@/views/admin/CreateFavorite.vue"),
+);
const favoritesStore = useFavoritesStore();
const authStore = useAuthStore();
@@ -15,22 +17,31 @@ const showCreate = ref(false);
-
-
-
- {{ showCreate ? "Create Favorite" : "favs" }}
-
- {{ showCreate ? "x" : "+" }}
-
-
-
-
-
-
-
-
+
+
+
+ {{ showCreate ? "Create Favorite" : "favs" }}
+
+ {{ showCreate ? "x" : "+" }}
+
+
+
+
+
+
+
+
diff --git a/vue/src/views/home/Feed.vue b/vue/src/views/home/Feed.vue
index eb9660b..48dc81a 100644
--- a/vue/src/views/home/Feed.vue
+++ b/vue/src/views/home/Feed.vue
@@ -7,7 +7,9 @@ import { ref, computed, defineAsyncComponent } from "vue";
import { useAuthStore } from "@/stores/auth";
import { usePostsStore } from "@/stores/posts";
-const CreatePost = defineAsyncComponent(() => import("@/views/admin/CreatePost.vue"));
+const CreatePost = defineAsyncComponent(
+ () => import("@/views/admin/CreatePost.vue"),
+);
const authStore = useAuthStore();
const postsStore = usePostsStore();
@@ -20,75 +22,70 @@ const rightCap = computed(() => idx.value === postsStore.postsCount - 1);
const post = computed(() => postsStore.posts[idx.value]);
const userOwnsPost = computed(
- () => post.value.author.username == authStore.user.username,
+ () => post.value.author.username == authStore.user.username,
);
function nextPost() {
- if (idx.value < postsStore.postsCount - 1) {
- idx.value++;
- }
+ if (idx.value < postsStore.postsCount - 1) {
+ idx.value++;
+ }
}
function prevPost() {
- if (idx.value > 0) {
- idx.value--;
- }
+ if (idx.value > 0) {
+ idx.value--;
+ }
}
function deletePost() {
- postsStore.deletePost(post.value);
+ postsStore.deletePost(post.value);
}
-
-
-
- {{ showCreate ? "Create Post" : post.title }}
-
- {{ showCreate ? "x" : "+" }}
-
-
-
-
-
+
+
+ {{ showCreate ? "Create Post" : post.title }}
+
- Created at:
- {{ new Date(post.createdAt).toLocaleString() }}
- By: {{ post.author.username }}
-
-
-
- Prev
-
-
- Next
-
-
- Delete
-
+ {{ showCreate ? "x" : "+" }}
+
+
+
+
+
+
Created at: {{ new Date(post.createdAt).toLocaleString() }}
+
By: {{ post.author.username }}
+
+
+
+ Prev
+
+
+ Next
+
+
+
Delete
+
diff --git a/vue/src/views/home/Gym.vue b/vue/src/views/home/Gym.vue
index 001fabc..179d842 100644
--- a/vue/src/views/home/Gym.vue
+++ b/vue/src/views/home/Gym.vue
@@ -2,25 +2,25 @@
import Header from "@/components/text/Header.vue";
import LinkTable from "@/components/util/LinkTable.vue";
const gym = [
- { name: "Row", type: "30 min" },
- { name: "Run", type: "5k" },
- { name: "Pushup & Squat", type: "50" },
+ { name: "Row", type: "30 min" },
+ { name: "Run", type: "5k" },
+ { name: "Pushup & Squat", type: "50" },
];
-
-
-
I'm not a gym geek
-
4/7 days I do:
-
-
-
+
+
+
I'm not a gym geek
+
4/7 days I do:
+
+
+
diff --git a/vue/src/views/home/Gym2.vue b/vue/src/views/home/Gym2.vue
index dc22991..41851b6 100644
--- a/vue/src/views/home/Gym2.vue
+++ b/vue/src/views/home/Gym2.vue
@@ -5,7 +5,9 @@ import { useHomeDataStore } from "@/stores/homeData";
import { useAuthStore } from "@/stores/auth";
import { storeToRefs } from "pinia";
-const CreateRowing = defineAsyncComponent(() => import("@/views/admin/CreateRowing.vue"));
+const CreateRowing = defineAsyncComponent(
+ () => import("@/views/admin/CreateRowing.vue"),
+);
const store = useHomeDataStore();
const authStore = useAuthStore();
@@ -117,13 +119,22 @@ function formatValue(key, val) {
{{ showCreate ? "Upload Rowing" : "Rowing" }}
-
+
{{ showCreate ? "x" : "+" }}
-
+
diff --git a/vue/src/views/home/Home.vue b/vue/src/views/home/Home.vue
index 57c47c7..09975a9 100644
--- a/vue/src/views/home/Home.vue
+++ b/vue/src/views/home/Home.vue
@@ -25,223 +25,219 @@ import Bookmarks from "./Bookmarks.vue";
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue/src/views/home/Intro.vue b/vue/src/views/home/Intro.vue
index 86b6aa4..51a7902 100644
--- a/vue/src/views/home/Intro.vue
+++ b/vue/src/views/home/Intro.vue
@@ -4,27 +4,29 @@ import Paragraph from "@/components/text/Paragraph.vue";
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue/src/views/home/Intro2.vue b/vue/src/views/home/Intro2.vue
index ede7694..a670224 100644
--- a/vue/src/views/home/Intro2.vue
+++ b/vue/src/views/home/Intro2.vue
@@ -3,46 +3,46 @@ import { rand } from "@vueuse/core";
import { ref, onMounted, onUnmounted, nextTick } from "vue";
interface Item {
- x: number;
- y: number;
- dx: number;
- dy: number;
- content: string;
+ x: number;
+ y: number;
+ dx: number;
+ dy: number;
+ content: string;
}
const container = ref
(null);
const itemEls = ref([]);
const phrases = [
- "Welcome to my website",
- "I'm looking to do a big revamp",
- "A4 sheets of paper are what I'm used to",
- "I'd love to know your recommendations",
- "for very short books",
- "Message me by any means necessary",
- "I like anime, all kinds of music and sci fic",
+ "Welcome to my website",
+ "I'm looking to do a big revamp",
+ "A4 sheets of paper are what I'm used to",
+ "I'd love to know your recommendations",
+ "for very short books",
+ "Message me by any means necessary",
+ "I like anime, all kinds of music and sci fic",
];
// Non-reactive animation state to avoid triggering Vue re-renders every frame
const animState = phrases.map((text, i) => ({
- x: 0,
- y: i * 20,
- dx: rand(0, 60) / 100,
- dy: 1.0,
- content: text,
- cachedW: 0,
- cachedH: 0,
+ x: 0,
+ y: i * 20,
+ dx: rand(0, 60) / 100,
+ dy: 1.0,
+ content: text,
+ cachedW: 0,
+ cachedH: 0,
}));
// Reactive items only for initial render
const items = ref- (
- animState.map((s) => ({
- x: s.x,
- y: s.y,
- dx: s.dx,
- dy: s.dy,
- content: s.content,
- })),
+ animState.map((s) => ({
+ x: s.x,
+ y: s.y,
+ dx: s.dx,
+ dy: s.dy,
+ content: s.content,
+ })),
);
let rafId = 0;
@@ -52,79 +52,76 @@ let lastFrameTime = 0;
const FRAME_INTERVAL = 1000 / 30;
function measureSizes() {
- const c = container.value;
- if (c) {
- cachedCW = c.clientWidth;
- cachedCH = c.clientHeight;
+ const c = container.value;
+ if (c) {
+ cachedCW = c.clientWidth;
+ cachedCH = c.clientHeight;
+ }
+ itemEls.value.forEach((el, i) => {
+ if (el && animState[i]) {
+ animState[i].cachedW = el.offsetWidth;
+ animState[i].cachedH = el.offsetHeight;
}
- itemEls.value.forEach((el, i) => {
- if (el && animState[i]) {
- animState[i].cachedW = el.offsetWidth;
- animState[i].cachedH = el.offsetHeight;
- }
- });
+ });
}
function animate(timestamp: number) {
- if (!cachedCW || !cachedCH) {
- rafId = requestAnimationFrame(animate);
- return;
- }
-
- if (timestamp - lastFrameTime < FRAME_INTERVAL) {
- rafId = requestAnimationFrame(animate);
- return;
- }
- lastFrameTime = timestamp;
-
- for (let i = 0; i < animState.length; i++) {
- const s = animState[i];
- const el = itemEls.value[i];
- if (!el) continue;
-
- s.x += s.dx;
- s.y += s.dy;
-
- if (s.x < 0 || s.x > cachedCW - s.cachedW) s.dx *= -1;
- if (s.y < 0 || s.y > cachedCH - s.cachedH) s.dy *= -1;
-
- el.style.transform = `translate(${s.x}px, ${s.y}px)`;
- }
-
+ if (!cachedCW || !cachedCH) {
rafId = requestAnimationFrame(animate);
+ return;
+ }
+
+ if (timestamp - lastFrameTime < FRAME_INTERVAL) {
+ rafId = requestAnimationFrame(animate);
+ return;
+ }
+ lastFrameTime = timestamp;
+
+ for (let i = 0; i < animState.length; i++) {
+ const s = animState[i];
+ const el = itemEls.value[i];
+ if (!el) continue;
+
+ s.x += s.dx;
+ s.y += s.dy;
+
+ if (s.x < 0 || s.x > cachedCW - s.cachedW) s.dx *= -1;
+ if (s.y < 0 || s.y > cachedCH - s.cachedH) s.dy *= -1;
+
+ el.style.transform = `translate(${s.x}px, ${s.y}px)`;
+ }
+
+ rafId = requestAnimationFrame(animate);
}
let resizeObserver: ResizeObserver;
onMounted(async () => {
- await nextTick();
- measureSizes();
- rafId = requestAnimationFrame(animate);
+ await nextTick();
+ measureSizes();
+ rafId = requestAnimationFrame(animate);
- resizeObserver = new ResizeObserver(measureSizes);
- resizeObserver.observe(container.value!);
+ resizeObserver = new ResizeObserver(measureSizes);
+ resizeObserver.observe(container.value!);
});
onUnmounted(() => {
- cancelAnimationFrame(rafId);
- resizeObserver?.disconnect();
+ cancelAnimationFrame(rafId);
+ resizeObserver?.disconnect();
});
+
-
-
- {{ item.content }}
-
-
+
+ {{ item.content }}
+
+
diff --git a/vue/src/views/home/Links.vue b/vue/src/views/home/Links.vue
index c92c533..d8edae9 100644
--- a/vue/src/views/home/Links.vue
+++ b/vue/src/views/home/Links.vue
@@ -4,31 +4,31 @@ import LinkTable from "@/components/util/LinkTable.vue";
import Header from "@/components/text/Header.vue";
const site_links = [
- { name: "CV", link: "/cv" },
- { name: "Bookmarks", link: "/bookmarks" },
- { name: "Shrines", link: "/shrines" },
- { name: "Admin", link: "/admin" },
+ { name: "CV", link: "/cv" },
+ { name: "Bookmarks", link: "/bookmarks" },
+ { name: "Shrines", link: "/shrines" },
+ { name: "Admin", link: "/admin" },
];
const social_links = [
- { name: "Gitea", link: "/gitea/explore/repos" },
- { name: "Steam", link: "https://steamcommunity.com/id/SteveThePug" },
- { name: "Github", link: "https://github.com/SteveThePug" },
- { name: "Spotify", link: "https://open.spotify.com/user/stevethepug" },
- { name: "Notes", link: "/notes/" },
+ { name: "Gitea", link: "/gitea/explore/repos" },
+ { name: "Steam", link: "https://steamcommunity.com/id/SteveThePug" },
+ { name: "Github", link: "https://github.com/SteveThePug" },
+ { name: "Spotify", link: "https://open.spotify.com/user/stevethepug" },
+ { name: "Notes", link: "/notes/" },
];
-
-
-
+
diff --git a/vue/src/views/home/Listening.vue b/vue/src/views/home/Listening.vue
index 698fcc0..3072d07 100644
--- a/vue/src/views/home/Listening.vue
+++ b/vue/src/views/home/Listening.vue
@@ -11,75 +11,76 @@ let nextId = null;
let refreshId = null;
function nextSong() {
- clearTimeout(nextId);
- nextId = setTimeout(nextSong, 5000);
- idx.value = (idx.value + 1) % songsStore.songsCount;
+ clearTimeout(nextId);
+ nextId = setTimeout(nextSong, 5000);
+ idx.value = (idx.value + 1) % songsStore.songsCount;
}
onMounted(() => {
- songsStore.fetchSongs();
- nextId = setTimeout(nextSong, 5000);
- refreshId = setInterval(songsStore.fetchSongs, 120000);
+ songsStore.fetchSongs();
+ nextId = setTimeout(nextSong, 5000);
+ refreshId = setInterval(songsStore.fetchSongs, 120000);
});
onUnmounted(() => {
- clearTimeout(nextId);
- clearInterval(refreshId);
+ clearTimeout(nextId);
+ clearInterval(refreshId);
});
-
+
-
-
-
-
- Song: {{ song.track.name }}
-
-
- Artist: {{ song.track.artists[0].name }}
-
-
+
+
+
+
Song: {{ song.track.name }}
+
+ Artist: {{ song.track.artists[0].name }}
+
+
-
+
diff --git a/vue/src/views/home/Miku.vue b/vue/src/views/home/Miku.vue
index 232740b..a68ed10 100644
--- a/vue/src/views/home/Miku.vue
+++ b/vue/src/views/home/Miku.vue
@@ -2,12 +2,12 @@
import Slideshow from "@/components/util/Slideshow.vue";
const images = [
- { url: "/img/miku/miku1.gif" },
- { url: "/img/miku/miku2.gif" },
- // { url: "/img/miku/miku2.png" },
+ { url: "/img/miku/miku1.gif" },
+ { url: "/img/miku/miku2.gif" },
+ // { url: "/img/miku/miku2.png" },
];
-
+
diff --git a/vue/src/views/home/Stamps.vue b/vue/src/views/home/Stamps.vue
index 51ceceb..f86e255 100644
--- a/vue/src/views/home/Stamps.vue
+++ b/vue/src/views/home/Stamps.vue
@@ -6,20 +6,20 @@ import Link from "@/components/text/Link.vue";
import { shuffleArray } from "@/js/utils.js";
let srcs = [
- "/img/stamps/portal.gif",
- "/img/stamps/miku.gif",
- "/img/stamps/utau.gif",
- "/img/stamps/teto.webp",
- "/img/stamps/3ds.jpg",
- "/img/stamps/fry.png",
- "/img/stamps/ai.png",
- "/img/stamps/rei.png",
- "/img/stamps/tetris.gif",
- "/img/stamps/tf2.gif",
- "/img/stamps/demo.gif",
- "/img/stamps/demo.gif",
- "/img/stamps/demo.gif",
- "/img/stamps/demo.gif",
+ "/img/stamps/portal.gif",
+ "/img/stamps/miku.gif",
+ "/img/stamps/utau.gif",
+ "/img/stamps/teto.webp",
+ "/img/stamps/3ds.jpg",
+ "/img/stamps/fry.png",
+ "/img/stamps/ai.png",
+ "/img/stamps/rei.png",
+ "/img/stamps/tetris.gif",
+ "/img/stamps/tf2.gif",
+ "/img/stamps/demo.gif",
+ "/img/stamps/demo.gif",
+ "/img/stamps/demo.gif",
+ "/img/stamps/demo.gif",
];
shuffleArray(srcs);
@@ -31,71 +31,76 @@ let dx = 0.2;
let dy = 0.12;
function bounce() {
- const el = touchscreen.value?.$el;
- if (!el) return;
+ const el = touchscreen.value?.$el;
+ if (!el) return;
- const maxX = el.scrollWidth - el.clientWidth;
- const maxY = el.scrollHeight - el.clientHeight;
+ const maxX = el.scrollWidth - el.clientWidth;
+ const maxY = el.scrollHeight - el.clientHeight;
- if (maxX > 0) {
- posX += dx;
- if (posX <= 0) {
- posX = 0;
- dx = -dx;
- } else if (posX >= maxX) {
- posX = maxX;
- dx = -dx;
- }
- el.scrollLeft = posX;
+ if (maxX > 0) {
+ posX += dx;
+ if (posX <= 0) {
+ posX = 0;
+ dx = -dx;
+ } else if (posX >= maxX) {
+ posX = maxX;
+ dx = -dx;
}
- if (maxY > 0) {
- posY += dy;
- if (posY <= 0) {
- posY = 0;
- dy = -dy;
- } else if (posY >= maxY) {
- posY = maxY;
- dy = -dy;
- }
- el.scrollTop = posY;
+ el.scrollLeft = posX;
+ }
+ if (maxY > 0) {
+ posY += dy;
+ if (posY <= 0) {
+ posY = 0;
+ dy = -dy;
+ } else if (posY >= maxY) {
+ posY = maxY;
+ dy = -dy;
}
+ el.scrollTop = posY;
+ }
- animId = requestAnimationFrame(bounce);
+ animId = requestAnimationFrame(bounce);
}
onMounted(() => {
- animId = requestAnimationFrame(bounce);
+ animId = requestAnimationFrame(bounce);
});
onUnmounted(() => {
- if (animId) cancelAnimationFrame(animId);
+ if (animId) cancelAnimationFrame(animId);
});
-
-
-
+
+
+
diff --git a/vue/src/views/home/Steam.vue b/vue/src/views/home/Steam.vue
index 85545dc..d7c084c 100644
--- a/vue/src/views/home/Steam.vue
+++ b/vue/src/views/home/Steam.vue
@@ -17,116 +17,116 @@ let nextId = null;
let refreshId = null;
function nextGame() {
- clearTimeout(nextId);
- nextId = setTimeout(nextGame, 5000);
- if (steamStatus.value.recentGames.length) {
- idx.value = (idx.value + 1) % steamStatus.value.recentGames.length;
- }
+ clearTimeout(nextId);
+ nextId = setTimeout(nextGame, 5000);
+ if (steamStatus.value.recentGames.length) {
+ idx.value = (idx.value + 1) % steamStatus.value.recentGames.length;
+ }
}
onMounted(() => {
- nextId = setTimeout(nextGame, 5000);
- refreshId = setInterval(() => steamStore.fetchSteam(), 5 * 60 * 1000);
+ nextId = setTimeout(nextGame, 5000);
+ refreshId = setInterval(() => steamStore.fetchSteam(), 5 * 60 * 1000);
});
onUnmounted(() => {
- clearTimeout(nextId);
- clearInterval(refreshId);
+ clearTimeout(nextId);
+ clearInterval(refreshId);
});
function formatHours(minutes) {
- const hrs = (minutes / 60).toFixed(1);
- return `${hrs}h`;
+ const hrs = (minutes / 60).toFixed(1);
+ return `${hrs}h`;
}
-
-
+
+
-
Loading...
+
Loading...
-
-
-
-
-
- {{ game.name }}
-
-
- {{ formatHours(game.playtime2Weeks) }} last 2 weeks
-
-
-
+
+
+
+
+
+ {{ game.name }}
+
+
+ {{ formatHours(game.playtime2Weeks) }} last 2 weeks
+
-
- No recent games.
+
+
+
No recent games.
+
diff --git a/vue/src/views/home/shrines/Demoman.vue b/vue/src/views/home/shrines/Demoman.vue
index e791982..c84529c 100644
--- a/vue/src/views/home/shrines/Demoman.vue
+++ b/vue/src/views/home/shrines/Demoman.vue
@@ -3,27 +3,25 @@ import VideoTable from "@/components/util/VideoTable.vue";
import Link from "@/components/text/Link.vue";
const videoSources = [
- { name: "demoman", link: "/img/demoman/1760582395316219.webm" },
- { name: "demoman", link: "/img/demoman/1761052136609718.webm" },
- { name: "demoman", link: "/img/demoman/1761088452011210.mp4" },
- { name: "demoman", link: "/img/demoman/1761570214170465.webm" },
- { name: "demoman", link: "/img/demoman/1761828457509465.webm" },
+ { name: "demoman", link: "/img/demoman/1760582395316219.webm" },
+ { name: "demoman", link: "/img/demoman/1761052136609718.webm" },
+ { name: "demoman", link: "/img/demoman/1761088452011210.mp4" },
+ { name: "demoman", link: "/img/demoman/1761570214170465.webm" },
+ { name: "demoman", link: "/img/demoman/1761828457509465.webm" },
];
-
-
-
+
+
+
diff --git a/vue/src/views/home/shrines/Evangelion.vue b/vue/src/views/home/shrines/Evangelion.vue
index 638d53c..c16e9ec 100644
--- a/vue/src/views/home/shrines/Evangelion.vue
+++ b/vue/src/views/home/shrines/Evangelion.vue
@@ -3,11 +3,11 @@ import Wip from "@/components/util/Wip.vue";
-
-
-
-
-
+
+
+
+
+
diff --git a/vue/src/views/home/shrines/GTO.vue b/vue/src/views/home/shrines/GTO.vue
index e945b5c..c16e9ec 100644
--- a/vue/src/views/home/shrines/GTO.vue
+++ b/vue/src/views/home/shrines/GTO.vue
@@ -4,7 +4,9 @@ import Wip from "@/components/util/Wip.vue";
-
+
diff --git a/vue/src/views/home/shrines/Shrines.vue b/vue/src/views/home/shrines/Shrines.vue
index 18ae86b..493a7e8 100644
--- a/vue/src/views/home/shrines/Shrines.vue
+++ b/vue/src/views/home/shrines/Shrines.vue
@@ -1,20 +1,20 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/vue/src/views/home/shrines/Skipskipbenben.vue b/vue/src/views/home/shrines/Skipskipbenben.vue
index 638d53c..c16e9ec 100644
--- a/vue/src/views/home/shrines/Skipskipbenben.vue
+++ b/vue/src/views/home/shrines/Skipskipbenben.vue
@@ -3,11 +3,11 @@ import Wip from "@/components/util/Wip.vue";
-
-
-
-
-
+
+
+
+
+
diff --git a/vue/src/views/landing/Landing.vue b/vue/src/views/landing/Landing.vue
index 8a62035..0fec28b 100644
--- a/vue/src/views/landing/Landing.vue
+++ b/vue/src/views/landing/Landing.vue
@@ -5,52 +5,51 @@ import Header from "@/components/text/Header.vue";
import Paragraph from "@/components/text/Paragraph.vue";
const links = [
- { name: "GitHub", href: "https://github.com/SteveThePug" },
- { name: "Gitea", href: "/gitea/explore/repos" },
- { name: "Spotify", href: "https://open.spotify.com/user/stevethepug" },
+ { name: "GitHub", href: "https://github.com/SteveThePug" },
+ { name: "Gitea", href: "/gitea/explore/repos" },
+ { name: "Spotify", href: "https://open.spotify.com/user/stevethepug" },
];
-
-
-
-
-
- Junior software engineer focused on full-stack development,
- systems programming, and infrastructure. First Class Honours
- in Computer Science with Mathematics from Leeds and
- Waterloo.
-
-
+
+
+
+
+
+ Junior software engineer focused on full-stack development, systems
+ programming, and infrastructure. First Class Honours in Computer
+ Science with Mathematics from Leeds and Waterloo.
+
+
-
-
-
- This website is self-hosted and has a lot more on it than it
- needs to. Please have a look at my
- CV for a full breakdown of
- my experience, projects, and skills. Please visit
- STP for the prefered but
- less professional experience.
-
-
+
+
+
+ This website is self-hosted and has a lot more on it than it needs to.
+ Please have a look at my
+ CV for a full breakdown of my
+ experience, projects, and skills. Please visit
+ STP for the prefered but less
+ professional experience.
+
+
-
- CV
- STP
- Email
-
- {{ link.name }}
-
-
-
-
+
+ CV
+ STP
+ Email
+
+ {{ link.name }}
+
+
+
+
diff --git a/vue/src/views/unused/CoverLetters.vue b/vue/src/views/unused/CoverLetters.vue
index 91f84c6..4c50574 100644
--- a/vue/src/views/unused/CoverLetters.vue
+++ b/vue/src/views/unused/CoverLetters.vue
@@ -1,72 +1,70 @@
-
-
-
-
- Companies
- Completed
-
-
-
-
- Lloyds
- YES
-
-
-
+
+
+
+
+ Companies
+ Completed
+
+
+
+
+ Lloyds
+ YES
+
+
+
-
-
-
-
BAE graduate digital intelligence software engineer
-
- I am writing to express my interest in your software engineering
- position. BAE Systems has hosted multiple stools at the
- University of Leeds and have always exhibited their development
- of leading-edge software and technology. This is where the
- origin of my interest in BAE systems emerged and I'm hopeful
- that this interest shall continue.
-
-
- I'm confidient im a strong fit for this role. My technical
- background includes extensive experience with frontend
- frameworks such as React. My devotion however lies more in
- backend development as has more potential to graple problems
- related to optimisation and designing coherent interfaces.
-
-
- The C# Programming Yellow Book was my first
- introduction to C# during A-Level, Java was our vessel for
- teaching object-orientated programming at university. I am
- confident I have the relevant experience to grasp the languages
- stated for the role I am applying for.
-
-
- My academic background in Computer Science and Mathematics has
- honed my ability to translate abstract concepts into structured,
- logical solutions. Just as I have transformed theoretical
- hypotheses into formal proofs, I aim to transform business
- requirements into robust, maintainable software systems through
- collaboration and rigorous reasoning.
-
-
Thank you for reading - Adam F
+
+
+
+
BAE graduate digital intelligence software engineer
+
+ I am writing to express my interest in your software engineering
+ position. BAE Systems has hosted multiple stools at the University of
+ Leeds and have always exhibited their development of leading-edge
+ software and technology. This is where the origin of my interest in BAE
+ systems emerged and I'm hopeful that this interest shall continue.
+
+
+ I'm confidient im a strong fit for this role. My technical background
+ includes extensive experience with frontend frameworks such as React. My
+ devotion however lies more in backend development as has more potential
+ to graple problems related to optimisation and designing coherent
+ interfaces.
+
+
+ The C# Programming Yellow Book was my first introduction to
+ C# during A-Level, Java was our vessel for teaching object-orientated
+ programming at university. I am confident I have the relevant experience
+ to grasp the languages stated for the role I am applying for.
+
+
+ My academic background in Computer Science and Mathematics has honed my
+ ability to translate abstract concepts into structured, logical
+ solutions. Just as I have transformed theoretical hypotheses into formal
+ proofs, I aim to transform business requirements into robust,
+ maintainable software systems through collaboration and rigorous
+ reasoning.
+
+
Thank you for reading - Adam F
+
+
diff --git a/vue/src/views/unused/Notes.vue b/vue/src/views/unused/Notes.vue
index b9f8f6e..9da9671 100644
--- a/vue/src/views/unused/Notes.vue
+++ b/vue/src/views/unused/Notes.vue
@@ -16,60 +16,60 @@ const path = Array.isArray(pathArray) ? pathArray.join("/") : pathArray;
const url = `/api/notes/${path}`;
function getFilename(headers) {
- const disposition = headers["content-disposition"];
- if (!disposition) return null;
+ const disposition = headers["content-disposition"];
+ if (!disposition) return null;
- const match = disposition.match(/filename="?([^"]+)"?/);
- return match ? match[1] : null;
+ const match = disposition.match(/filename="?([^"]+)"?/);
+ return match ? match[1] : null;
}
async function fetchFile() {
- const response = await axios.get(url, { responseType: "blob" });
- filename.value = getFilename(response.headers);
+ const response = await axios.get(url, { responseType: "blob" });
+ filename.value = getFilename(response.headers);
- const lastModified = response.headers["last-modified"];
- last_edited.value = lastModified ? new Date(lastModified) : null;
+ const lastModified = response.headers["last-modified"];
+ last_edited.value = lastModified ? new Date(lastModified) : null;
- if (filename.value.toLowerCase().endsWith(".md")) {
- const text = await response.data.text();
- file.value = fixLinks(text);
- } else {
- file.value = response.data;
- }
+ if (filename.value.toLowerCase().endsWith(".md")) {
+ const text = await response.data.text();
+ file.value = fixLinks(text);
+ } else {
+ file.value = response.data;
+ }
}
function fixLinks(filedata) {
- return filedata.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) => {
- if (
- url.startsWith("http://") ||
- url.startsWith("https://") ||
- url.startsWith("#") ||
- url.startsWith("./") ||
- url.startsWith("../") ||
- url.startsWith("//")
- ) {
- return match;
- }
+ return filedata.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) => {
+ if (
+ url.startsWith("http://") ||
+ url.startsWith("https://") ||
+ url.startsWith("#") ||
+ url.startsWith("./") ||
+ url.startsWith("../") ||
+ url.startsWith("//")
+ ) {
+ return match;
+ }
- return `[${text}](/notes/${url})`;
- });
+ return `[${text}](/notes/${url})`;
+ });
}
onMounted(fetchFile);
-
-
-
-
{{ filename }}
- {{ last_edited }}
-
-
+
+
+
+
{{ filename }}
+ {{ last_edited }}
+
+
- Loading…
-
+ Loading…
+
diff --git a/vue/vite.config.js b/vue/vite.config.js
index ebae6dd..be58331 100644
--- a/vue/vite.config.js
+++ b/vue/vite.config.js
@@ -9,25 +9,25 @@ import topLevelAwait from "vite-plugin-top-level-await";
// https://vite.dev/config/
export default defineConfig({
- plugins: [
- vue(),
- ...(process.env.NODE_ENV !== "production" ? [vueDevTools()] : []),
- tailwindcss(),
- wasm(),
- topLevelAwait(),
- ],
- resolve: {
- alias: {
- "@": fileURLToPath(new URL("./src", import.meta.url)),
- },
+ plugins: [
+ vue(),
+ ...(process.env.NODE_ENV !== "production" ? [vueDevTools()] : []),
+ tailwindcss(),
+ wasm(),
+ topLevelAwait(),
+ ],
+ resolve: {
+ alias: {
+ "@": fileURLToPath(new URL("./src", import.meta.url)),
},
- server: {
- host: "0.0.0.0",
- proxy: {
- "/api": "http://localhost:8080",
- "/gitea": "http://localhost:3000",
- "/radio": "http://localhost:8000",
- "/searxng": "http://localhost:8080",
- },
+ },
+ server: {
+ host: "0.0.0.0",
+ proxy: {
+ "/api": "http://localhost:8080",
+ "/gitea": "http://localhost:3000",
+ "/radio": "http://localhost:8000",
+ "/searxng": "http://localhost:8080",
},
+ },
});