Compare commits
No commits in common. "af44880f59f7fc2823393ce21ce41e12f16dfdfb" and "92b78e9c40c4659fbaa1fafd5277e289dbc7aea8" have entirely different histories.
af44880f59
...
92b78e9c40
18 changed files with 54 additions and 506 deletions
|
@ -94,12 +94,6 @@ input {
|
||||||
width: 80%; /* Could be more or less, depending on screen size */
|
width: 80%; /* Could be more or less, depending on screen size */
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
line-height: calc(2 / 1.5);
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-pointer {
|
.hover-pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { logout } from "~/composables/logout";
|
|
||||||
|
|
||||||
let isOpened = ref(false);
|
|
||||||
const menuRef = ref<HTMLElement>();
|
|
||||||
|
|
||||||
const toggleMenu = function () {
|
|
||||||
isOpened.value = !isOpened.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
const handleClickOutside = (e: Event) => {
|
|
||||||
if (!menuRef.value?.contains(e.target as Node)) {
|
|
||||||
isOpened.value = false;
|
|
||||||
} else {
|
|
||||||
const target = e.target as HTMLElement;
|
|
||||||
if (
|
|
||||||
target.classList.contains("menu-link") ||
|
|
||||||
target.closest(".menu-link")
|
|
||||||
) {
|
|
||||||
isOpened.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("click", handleClickOutside);
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
document.removeEventListener("click", handleClickOutside);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div ref="menuRef" class="profile-menu">
|
|
||||||
<img
|
|
||||||
alt="profile menu"
|
|
||||||
class="profile-pic"
|
|
||||||
src="https://placecage.lucidinternets.com/50/50"
|
|
||||||
tabindex="0"
|
|
||||||
@click="toggleMenu"
|
|
||||||
@keydown.enter="toggleMenu"
|
|
||||||
@keydown.space="toggleMenu"
|
|
||||||
/>
|
|
||||||
<div class="menu-content">
|
|
||||||
<ul v-show="isOpened">
|
|
||||||
<li role="none">
|
|
||||||
<NuxtLink class="menu-link" to="/admin">Admin</NuxtLink>
|
|
||||||
</li>
|
|
||||||
<li role="none">
|
|
||||||
<NuxtLink class="menu-link" to="/user/profile"> Profile</NuxtLink>
|
|
||||||
</li>
|
|
||||||
<!--
|
|
||||||
<li role="none">
|
|
||||||
<NuxtLink class="menu-link" to="/user/settings"> Settings</NuxtLink>
|
|
||||||
</li>
|
|
||||||
-->
|
|
||||||
<li
|
|
||||||
id="logout"
|
|
||||||
class="menu-link"
|
|
||||||
role="none"
|
|
||||||
tabindex="0"
|
|
||||||
@click="logout"
|
|
||||||
>
|
|
||||||
Logout
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.profile-menu {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-pic {
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-pic:hover {
|
|
||||||
border: 1px solid #6f0b51;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-content {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
right: 0;
|
|
||||||
min-width: 150px;
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
|
|
||||||
z-index: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-content li {
|
|
||||||
color: black;
|
|
||||||
text-decoration: none;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-content li:hover {
|
|
||||||
background-color: #6f0b51;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-link {
|
|
||||||
padding: 12px 16px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<div
|
|
||||||
class="grid grid-rows-2 text-center sm:text-left sm:grid-rows-none sm:grid-cols-2 my-5 navbar w-full"
|
|
||||||
>
|
|
||||||
<NuxtLink class="block" to="/">
|
|
||||||
<h1 class="block site-title bloodseeker">Cinema Corona</h1>
|
|
||||||
</NuxtLink>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
class="mt-3 sm:mt-0 justify-self-center sm:justify-self-end inline-flex space-x-5 bloodseeker leading-10"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<NuxtLink class="text-xl header-link" to="/lists">Lists</NuxtLink>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<NuxtLink class="text-xl header-link" to="/schedule">Schedule</NuxtLink>
|
|
||||||
</li>
|
|
||||||
<li v-if="authenticated">
|
|
||||||
<ProfileMenu />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { hasToken } from "~/composables/hasToken";
|
|
||||||
|
|
||||||
const authenticated = computed(() => hasToken());
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<script lang="ts" setup></script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<button class="btn p-3 mt-5" type="button">
|
|
||||||
<slot> </slot>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
|
@ -1,21 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import FormButton from "~/components/common/ui/FormButton.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<h3 class="text-bold text-xl">Reset Password</h3>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<label for="old_password">Old Password</label>
|
|
||||||
<input id="old_password" class="p-3" name="password" type="password" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<label for="password">New Password</label>
|
|
||||||
<input id="password" class="p-3" name="password" type="password" />
|
|
||||||
</div>
|
|
||||||
<FormButton>Update Password</FormButton>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
26
src/components/navbar.vue
Normal file
26
src/components/navbar.vue
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div class="grid grid-rows-2 text-center sm:text-left sm:grid-rows-none sm:grid-cols-2 my-5 navbar w-full">
|
||||||
|
<NuxtLink class="block" to="/admin">
|
||||||
|
<h1 class="block site-title bloodseeker">Cinema Corona</h1>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<ul class="mt-3 sm:mt-0 justify-self-center sm:justify-self-end inline-flex space-x-5 bloodseeker leading-10">
|
||||||
|
<li>
|
||||||
|
<NuxtLink class="text-xl header-link" to="/lists">Lists</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<NuxtLink class="text-xl header-link" to="/schedule">Schedule</NuxtLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "navbar",
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,6 +0,0 @@
|
||||||
import { useCookie } from "#app";
|
|
||||||
|
|
||||||
export function hasToken() {
|
|
||||||
const token = useCookie("token").value;
|
|
||||||
return token !== null && token !== undefined && token !== "";
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { useCookie } from "#app";
|
|
||||||
|
|
||||||
export function logout() {
|
|
||||||
let config = useRuntimeConfig();
|
|
||||||
fetch(`${config.public.apiURL}/auth/logout/`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-type": "application/json",
|
|
||||||
Authorization: `Token ${useCookie("token").value}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => response)
|
|
||||||
.then((_json) => {
|
|
||||||
let token = useCookie("token");
|
|
||||||
token.value = null;
|
|
||||||
navigateTo("/");
|
|
||||||
})
|
|
||||||
.catch((err) => console.log(err));
|
|
||||||
}
|
|
|
@ -6,11 +6,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Navbar from "~/components/common/navigation/navbar.vue";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "default",
|
name: "default",
|
||||||
components: { Navbar },
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,7 @@ export default defineNuxtConfig({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: ["@nuxtjs/tailwindcss", "@vesp/nuxt-fontawesome"],
|
modules: ["@nuxtjs/tailwindcss"],
|
||||||
fontawesome: {
|
|
||||||
icons: {
|
|
||||||
solid: ["user"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
css: ["@/assets/css/main.css"],
|
css: ["@/assets/css/main.css"],
|
||||||
compatibilityDate: "2025-04-05",
|
compatibilityDate: "2025-04-05",
|
||||||
|
|
||||||
|
|
77
src/package-lock.json
generated
77
src/package-lock.json
generated
|
@ -9,12 +9,8 @@
|
||||||
"lazysizes": "^5.3.2"
|
"lazysizes": "^5.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
|
||||||
"@nuxtjs/tailwindcss": "^6.2.0",
|
"@nuxtjs/tailwindcss": "^6.2.0",
|
||||||
"@types/node": "^22.14.0",
|
"@types/node": "^22.14.0",
|
||||||
"@vesp/nuxt-fontawesome": "^1.2.1",
|
|
||||||
"nuxt": "3.x",
|
"nuxt": "3.x",
|
||||||
"prettier": "3.x",
|
"prettier": "3.x",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
|
@ -975,68 +971,6 @@
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fortawesome/fontawesome-common-types": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/fontawesome-svg-core": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/free-brands-svg-icons": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "(CC-BY-4.0 AND MIT)",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/free-regular-svg-icons": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "(CC-BY-4.0 AND MIT)",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/free-solid-svg-icons": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "(CC-BY-4.0 AND MIT)",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@ioredis/commands": {
|
"node_modules/@ioredis/commands": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||||
|
@ -2893,17 +2827,6 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vesp/nuxt-fontawesome": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vesp/nuxt-fontawesome/-/nuxt-fontawesome-1.2.1.tgz",
|
|
||||||
"integrity": "sha512-W7gaCQ8szFmOsMwBcxq22vyAV7wARQ8TK5wsd1we8Gt3KPFVQHj9ZYi738b4ePoeFxYGBEndh/uMLY6sIc+9HQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
|
||||||
"@nuxt/kit": "^3.13.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@vitejs/plugin-vue": {
|
"node_modules/@vitejs/plugin-vue": {
|
||||||
"version": "5.2.3",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.3.tgz",
|
||||||
|
|
|
@ -8,12 +8,8 @@
|
||||||
"postinstall": "nuxt prepare"
|
"postinstall": "nuxt prepare"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
|
||||||
"@nuxtjs/tailwindcss": "^6.2.0",
|
"@nuxtjs/tailwindcss": "^6.2.0",
|
||||||
"@types/node": "^22.14.0",
|
"@types/node": "^22.14.0",
|
||||||
"@vesp/nuxt-fontawesome": "^1.2.1",
|
|
||||||
"nuxt": "3.x",
|
"nuxt": "3.x",
|
||||||
"prettier": "3.x",
|
"prettier": "3.x",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
|
|
|
@ -54,9 +54,9 @@ import AddMovie from "~/components/modal-content/AddMovie.vue";
|
||||||
import Search from "~/components/admin/search.vue";
|
import Search from "~/components/admin/search.vue";
|
||||||
import Showings from "~/components/admin/showings.vue";
|
import Showings from "~/components/admin/showings.vue";
|
||||||
import Lists from "~/components/admin/lists.vue";
|
import Lists from "~/components/admin/lists.vue";
|
||||||
|
import { useCookie } from "#app";
|
||||||
import type { Movie } from "~/types/movie";
|
import type { Movie } from "~/types/movie";
|
||||||
import Modal from "~/components/common/ui/Modal.vue";
|
import Modal from "~/components/Modal.vue";
|
||||||
import { logout } from "~/composables/logout";
|
|
||||||
|
|
||||||
const modal_movie = defineModel<Movie>("#movie-modal");
|
const modal_movie = defineModel<Movie>("#movie-modal");
|
||||||
|
|
||||||
|
@ -87,6 +87,30 @@ const toggleDisplay = function (element_id: string) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const logout = () => {
|
||||||
|
let config = useRuntimeConfig();
|
||||||
|
fetch(`${config.public.apiURL}/auth/logout/`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-type": "application/json",
|
||||||
|
Authorization: `Token ${useCookie("token").value}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => response)
|
||||||
|
.then((_json) => {
|
||||||
|
let token = useCookie("token");
|
||||||
|
token.value = null;
|
||||||
|
navigateTo("/");
|
||||||
|
})
|
||||||
|
.catch((err) => console.log(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const token = useCookie("token").value;
|
||||||
|
if (!token) {
|
||||||
|
navigateTo("/");
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -78,7 +78,7 @@ import ShowMovie from "~/components/modal-content/ShowMovie.vue";
|
||||||
import "lazysizes";
|
import "lazysizes";
|
||||||
import type { MovieList } from "~/types/movielist";
|
import type { MovieList } from "~/types/movielist";
|
||||||
import type { Movie } from "~/types/movie";
|
import type { Movie } from "~/types/movie";
|
||||||
import Modal from "~/components/common/ui/Modal.vue";
|
import Modal from "~/components/Modal.vue";
|
||||||
import { useCookie } from "#app";
|
import { useCookie } from "#app";
|
||||||
import { $fetch } from "ofetch";
|
import { $fetch } from "ofetch";
|
||||||
import MoviePoster from "~/components/MoviePoster.vue";
|
import MoviePoster from "~/components/MoviePoster.vue";
|
||||||
|
|
|
@ -1,143 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { useCookie } from "#app";
|
|
||||||
import type { UserProfile } from "~/types/userProfile";
|
|
||||||
|
|
||||||
const config = useRuntimeConfig();
|
|
||||||
|
|
||||||
const profile = defineModel<UserProfile>("profile");
|
|
||||||
const loading = ref(true);
|
|
||||||
|
|
||||||
const getProfile = async function () {
|
|
||||||
await $fetch<UserProfile>(`${config.public.apiURL}/users/profile`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Token ${useCookie("token").value}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
profile.value = data;
|
|
||||||
loading.value = false;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
if (err.statusCode === 401) {
|
|
||||||
useCookie("token").value = null;
|
|
||||||
navigateTo("/");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatDate = function (date_string: string) {
|
|
||||||
return new Date(date_string).toLocaleDateString();
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(getProfile);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<LoadingIcon v-if="loading" show-quote="true" />
|
|
||||||
<div v-else>
|
|
||||||
<h2 class="page-header">Profile</h2>
|
|
||||||
<div id="profile-card" class="movie-card neon-border">
|
|
||||||
<div id="user-data">
|
|
||||||
<div id="profile-picture">
|
|
||||||
<img
|
|
||||||
alt="profile image"
|
|
||||||
class="user-icon neon-border"
|
|
||||||
src="https://placecage.lucidinternets.com/g/200/200"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ul class="profile-details">
|
|
||||||
<li class="user-detail">
|
|
||||||
<label for="name">Name</label>
|
|
||||||
<span id="name">{{ profile?.name || profile?.username }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="user-detail">
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<span id="username">{{ profile?.username }}@movienight.social</span>
|
|
||||||
</li>
|
|
||||||
<li class="user-detail">
|
|
||||||
<label for="date-joined">Date Joined</label>
|
|
||||||
<span id="date-joined">{{
|
|
||||||
formatDate(profile?.date_joined || "")
|
|
||||||
}}</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="neon-border my-5" />
|
|
||||||
|
|
||||||
<div id="extra-fields">
|
|
||||||
<div id="movielists">
|
|
||||||
<h3 class="section-header">Lists</h3>
|
|
||||||
<ul id="movielist-list">
|
|
||||||
<li v-for="list in profile?.lists">
|
|
||||||
<NuxtLink :to="`/lists/${list.id}`">{{ list.name }}</NuxtLink>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
label {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
line-height: calc(2 / 1.5);
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#user-data {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-detail {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-icon {
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-details {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
list-style: none;
|
|
||||||
margin: 3rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.movie-card {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.movie-review {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#extra-fields {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (width >= 48rem) {
|
|
||||||
#user-data {
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,50 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import PasswordResetForm from "~/components/forms/PasswordReset.vue";
|
|
||||||
|
|
||||||
const timezones = Intl.supportedValuesOf("timeZone");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<h2 class="page-header">Settings</h2>
|
|
||||||
|
|
||||||
<div class="movie-card neon-border">
|
|
||||||
<form action="#" class="flex flex-col gap-5">
|
|
||||||
<label class="text-bold text-xl" for="site-name">Site Name</label>
|
|
||||||
<input
|
|
||||||
id="site-name"
|
|
||||||
class="p-3"
|
|
||||||
name="site-name"
|
|
||||||
placeholder="Movie Night"
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h3 class="text-bold text-xl">Locale</h3>
|
|
||||||
<!--SET TIMEZONE -->
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<label for="timezone">Timezone</label>
|
|
||||||
<select id="timezone" name="timezone">
|
|
||||||
<option v-for="timezone in timezones" :value="timezone">
|
|
||||||
{{ timezone }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="my-5 neon-border" />
|
|
||||||
|
|
||||||
<PasswordResetForm />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.movie-card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#timezone {
|
|
||||||
color: black;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,8 +0,0 @@
|
||||||
import type { MovieList } from "~/types/movielist";
|
|
||||||
|
|
||||||
export type UserProfile = {
|
|
||||||
name: string;
|
|
||||||
username: string;
|
|
||||||
date_joined: string;
|
|
||||||
lists: MovieList[];
|
|
||||||
};
|
|
Loading…
Add table
Add a link
Reference in a new issue