fix: more eslint issues

This commit is contained in:
Huskydog9988
2025-04-13 22:10:28 -04:00
parent 86c2d00726
commit e362f732e7
18 changed files with 71 additions and 66 deletions
+4 -4
View File
@@ -18,8 +18,8 @@ const carousel = inject(injectCarousel)!;
const amount = carousel.maxSlide - carousel.minSlide + 1; const amount = carousel.maxSlide - carousel.minSlide + 1;
function slideTo(index: number) { // function slideTo(index: number) {
const offsetIndex = index + carousel.minSlide; // const offsetIndex = index + carousel.minSlide;
carousel.nav.slideTo(offsetIndex); // carousel.nav.slideTo(offsetIndex);
} // }
</script> </script>
+1 -1
View File
@@ -58,7 +58,7 @@ const emit = defineEmits<{
created: [collectionId: string]; created: [collectionId: string];
}>(); }>();
const open: Ref<boolean> = defineModel<boolean>(); const open = defineModel<boolean>({ required: true });
const collectionName = ref(""); const collectionName = ref("");
const createCollectionLoading = ref(false); const createCollectionLoading = ref(false);
+2 -2
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="flex flex-row items-center gap-x-2"> <div class="flex flex-row items-center gap-x-2">
<img :src="game.icon" class="w-12 h-12 rounded-sm object-cover" > <img :src="game.icon" class="w-12 h-12 rounded-sm object-cover" />
<div class="flex flex-col items-left"> <div class="flex flex-col items-left">
<h1 class="font-semibold font-display text-lg text-zinc-100"> <h1 class="font-semibold font-display text-lg text-zinc-100">
{{ game.name }} {{ game.name }}
@@ -18,7 +18,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { GameMetadataSearchResult } from "~/server/internal/metadata/types"; import type { GameMetadataSearchResult } from "~/server/internal/metadata/types";
const props = defineProps<{ const { game } = defineProps<{
game: GameMetadataSearchResult & { sourceName?: string }; game: GameMetadataSearchResult & { sourceName?: string };
}>(); }>();
</script> </script>
+7 -6
View File
@@ -14,7 +14,7 @@
autocomplete="off" autocomplete="off"
class="block w-full rounded-md bg-zinc-900 py-2 pl-9 pr-2 text-sm text-zinc-100 outline outline-1 -outline-offset-1 outline-zinc-700 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-blue-600" class="block w-full rounded-md bg-zinc-900 py-2 pl-9 pr-2 text-sm text-zinc-100 outline outline-1 -outline-offset-1 outline-zinc-700 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-blue-600"
placeholder="Search library..." placeholder="Search library..."
> />
<MagnifyingGlassIcon <MagnifyingGlassIcon
class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400" class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400"
aria-hidden="true" aria-hidden="true"
@@ -37,9 +37,11 @@
:src="useObject(game.mCoverId)" :src="useObject(game.mCoverId)"
class="h-9 w-9 flex-shrink-0 rounded transition-all duration-300 group-hover:scale-105 hover:rotate-[-2deg] hover:shadow-lg" class="h-9 w-9 flex-shrink-0 rounded transition-all duration-300 group-hover:scale-105 hover:rotate-[-2deg] hover:shadow-lg"
alt="" alt=""
> />
<div class="min-w-0 flex-1 pl-2.5"> <div class="min-w-0 flex-1 pl-2.5">
<p class="text-sm font-semibold text-display text-zinc-200 truncate text-left"> <p
class="text-sm font-semibold text-display text-zinc-200 truncate text-left"
>
{{ game.mName }} {{ game.mName }}
</p> </p>
</div> </div>
@@ -57,7 +59,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { HomeIcon } from "@heroicons/vue/24/outline";
import { Bars3Icon, MagnifyingGlassIcon } from "@heroicons/vue/24/solid"; import { Bars3Icon, MagnifyingGlassIcon } from "@heroicons/vue/24/solid";
const library = await useLibrary(); const library = await useLibrary();
@@ -68,7 +69,7 @@ const filteredLibrary = computed(() =>
library.value.entries library.value.entries
.map((e) => e.game) .map((e) => e.game)
.filter((e) => .filter((e) =>
e.mName.toLowerCase().includes(searchQuery.value.toLowerCase()) e.mName.toLowerCase().includes(searchQuery.value.toLowerCase()),
) ),
); );
</script> </script>
+11 -10
View File
@@ -29,7 +29,7 @@
autocomplete="off" autocomplete="off"
class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500" class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500"
required required
> />
</div> </div>
<div> <div>
@@ -42,7 +42,7 @@
type="text" type="text"
class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500" class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500"
required required
> />
</div> </div>
<div> <div>
@@ -124,8 +124,8 @@
accept="image/*" accept="image/*"
class="hidden" class="hidden"
type="file" type="file"
@change="(e) => file = (e.target as any)?.files" @change="(e) => (file = (e.target as any)?.files)"
> />
</div> </div>
<div> <div>
@@ -155,7 +155,7 @@
placeholder="Add a tag..." placeholder="Add a tag..."
class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500" class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500"
@keydown.enter.prevent="addTag" @keydown.enter.prevent="addTag"
> />
<button <button
type="button" type="button"
class="mt-1 px-3 py-2 rounded-md bg-zinc-800 text-zinc-100 hover:bg-zinc-700" class="mt-1 px-3 py-2 rounded-md bg-zinc-800 text-zinc-100 hover:bg-zinc-700"
@@ -207,12 +207,10 @@ import {
XCircleIcon, XCircleIcon,
XMarkIcon, XMarkIcon,
} from "@heroicons/vue/24/solid"; } from "@heroicons/vue/24/solid";
import type { Article } from "@prisma/client";
import { micromark } from "micromark"; import { micromark } from "micromark";
import type { SerializeObject } from "nitropack/types";
const news = useNews(); const news = useNews();
if(!news.value){ if (!news.value) {
news.value = await fetchNews(); news.value = await fetchNews();
} }
@@ -230,6 +228,8 @@ const newArticle = ref({
}); });
const markdownPreview = computed(() => { const markdownPreview = computed(() => {
// TODO: maybe?? add https://github.com/cure53/DOMPurify
// micromark says its safe, but this is straight html we are injecting
return micromark(newArticle.value.content); return micromark(newArticle.value.content);
}); });
@@ -302,7 +302,7 @@ function addTag() {
function removeTag(tagToRemove: string) { function removeTag(tagToRemove: string) {
newArticle.value.tags = newArticle.value.tags.filter( newArticle.value.tags = newArticle.value.tags.filter(
(tag) => tag !== tagToRemove (tag) => tag !== tagToRemove,
); );
} }
@@ -367,7 +367,8 @@ async function createArticle() {
modalOpen.value = false; modalOpen.value = false;
} catch (e) { } catch (e) {
error.value = (e as any)?.statusMessage ?? "An unknown error occured."; // @ts-expect-error attempt to get statusMessage on error
error.value = e?.statusMessage ?? "An unknown error occured.";
} finally { } finally {
loading.value = false; loading.value = false;
} }
+14 -9
View File
@@ -21,7 +21,7 @@
type="text" type="text"
class="block w-full rounded-md border-0 bg-zinc-800 py-2.5 pl-10 pr-3 text-zinc-100 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-500 sm:text-sm sm:leading-6" class="block w-full rounded-md border-0 bg-zinc-800 py-2.5 pl-10 pr-3 text-zinc-100 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-500 sm:text-sm sm:leading-6"
placeholder="Search articles..." placeholder="Search articles..."
> />
</div> </div>
</div> </div>
@@ -85,7 +85,7 @@
<img <img
:src="useObject(article.image)" :src="useObject(article.image)"
class="absolute blur-sm inset-0 w-full h-full object-cover transition-all duration-200 group-hover:scale-110" class="absolute blur-sm inset-0 w-full h-full object-cover transition-all duration-200 group-hover:scale-110"
> />
<div <div
class="absolute inset-0 bg-gradient-to-b from-transparent to-zinc-800 transition-all duration-200" class="absolute inset-0 bg-gradient-to-b from-transparent to-zinc-800 transition-all duration-200"
/> />
@@ -117,7 +117,7 @@ import { MagnifyingGlassIcon } from "@heroicons/vue/24/solid";
import { micromark } from "micromark"; import { micromark } from "micromark";
const news = useNews(); const news = useNews();
if(!news.value){ if (!news.value) {
news.value = await fetchNews(); news.value = await fetchNews();
} }
@@ -154,6 +154,7 @@ const formatDate = (date: string) => {
}; };
const formatExcerpt = (excerpt: string) => { const formatExcerpt = (excerpt: string) => {
// TODO: same as one in NewsArticleCreateButton
// Convert markdown to HTML // Convert markdown to HTML
const html = micromark(excerpt); const html = micromark(excerpt);
// Strip HTML tags using regex // Strip HTML tags using regex
@@ -175,28 +176,32 @@ const filteredArticles = computed(() => {
const now = new Date(); const now = new Date();
let matchesDate = true; let matchesDate = true;
switch (dateFilter.value) { switch (dateFilter.value.toLowerCase()) {
case "today": case "today": {
matchesDate = articleDate.toDateString() === now.toDateString(); matchesDate = articleDate.toDateString() === now.toDateString();
break; break;
case "week": }
case "week": {
const weekAgo = new Date(now.setDate(now.getDate() - 7)); const weekAgo = new Date(now.setDate(now.getDate() - 7));
matchesDate = articleDate >= weekAgo; matchesDate = articleDate >= weekAgo;
break; break;
case "month": }
case "month": {
matchesDate = matchesDate =
articleDate.getMonth() === now.getMonth() && articleDate.getMonth() === now.getMonth() &&
articleDate.getFullYear() === now.getFullYear(); articleDate.getFullYear() === now.getFullYear();
break; break;
case "year": }
case "year": {
matchesDate = articleDate.getFullYear() === now.getFullYear(); matchesDate = articleDate.getFullYear() === now.getFullYear();
break; break;
} }
}
const matchesTags = const matchesTags =
selectedTags.value.length === 0 || selectedTags.value.length === 0 ||
selectedTags.value.every((tag) => selectedTags.value.every((tag) =>
article.tags.find((e) => e.name == tag) article.tags.find((e) => e.name == tag),
); );
return matchesSearch && matchesDate && matchesTags; return matchesSearch && matchesDate && matchesTags;
+5 -4
View File
@@ -60,8 +60,8 @@
:accept="props.accept" :accept="props.accept"
class="hidden" class="hidden"
type="file" type="file"
@change="(e) => file = (e.target as any)?.files" @change="(e) => (file = (e.target as any)?.files)"
> />
</div> </div>
</div> </div>
</div> </div>
@@ -112,14 +112,15 @@ import { ref } from "vue";
import { import {
Dialog, Dialog,
DialogPanel, DialogPanel,
DialogTitle,
TransitionChild, TransitionChild,
TransitionRoot, TransitionRoot,
} from "@headlessui/vue"; } from "@headlessui/vue";
import { ArrowUpTrayIcon } from "@heroicons/vue/20/solid"; import { ArrowUpTrayIcon } from "@heroicons/vue/20/solid";
import { XCircleIcon } from "@heroicons/vue/24/solid"; import { XCircleIcon } from "@heroicons/vue/24/solid";
const open: Ref<boolean> = defineModel<boolean>() as any; const open = defineModel<boolean>({
required: true,
});
const file = ref<FileList | undefined>(); const file = ref<FileList | undefined>();
const currentFile = computed(() => file.value?.item(0)); const currentFile = computed(() => file.value?.item(0));
+3 -7
View File
@@ -6,7 +6,7 @@
<img <img
:src="useObject(user.profilePicture)" :src="useObject(user.profilePicture)"
class="w-5 h-5 rounded-sm" class="w-5 h-5 rounded-sm"
> />
<span class="ml-2 text-sm font-bold">{{ user.displayName }}</span> <span class="ml-2 text-sm font-bold">{{ user.displayName }}</span>
<ChevronDownIcon class="ml-3 h-4" /> <ChevronDownIcon class="ml-3 h-4" />
</div> </div>
@@ -33,7 +33,7 @@
<img <img
:src="useObject(user.profilePicture)" :src="useObject(user.profilePicture)"
class="w-5 h-5 rounded-sm" class="w-5 h-5 rounded-sm"
> />
<span class="ml-2 text-sm font-bold">{{ user.displayName }}</span> <span class="ml-2 text-sm font-bold">{{ user.displayName }}</span>
</div> </div>
</NuxtLink> </NuxtLink>
@@ -45,6 +45,7 @@
v-slot="{ active, close }" v-slot="{ active, close }"
hydrate-on-visible hydrate-on-visible
> >
<!-- TODO: think this would work better as a NuxtLink instead of a button -->
<button <button
:href="nav.route" :href="nav.route"
:class="[ :class="[
@@ -92,9 +93,4 @@ const navigation: NavigationItem[] = [
].filter((e) => e !== undefined); ].filter((e) => e !== undefined);
const router = useRouter(); const router = useRouter();
function navigateLink(href: string, closeFn: () => any) {
closeFn();
router.push(href);
}
</script> </script>
+5 -3
View File
@@ -6,7 +6,7 @@ type FullCollection = Collection & {
}; };
export const useCollections = async () => { export const useCollections = async () => {
// @ts-expect-error // @ts-expect-error undefined is used to tell if value has been fetched or not
const state = useState<FullCollection[]>("collections", () => undefined); const state = useState<FullCollection[]>("collections", () => undefined);
if (state.value === undefined) { if (state.value === undefined) {
state.value = await $dropFetch<FullCollection[]>("/api/v1/collection"); state.value = await $dropFetch<FullCollection[]>("/api/v1/collection");
@@ -17,7 +17,9 @@ export const useCollections = async () => {
export async function refreshCollection(id: string) { export async function refreshCollection(id: string) {
const state = useState<FullCollection[]>("collections"); const state = useState<FullCollection[]>("collections");
const collection = await $dropFetch<FullCollection>(`/api/v1/collection/${id}`); const collection = await $dropFetch<FullCollection>(
`/api/v1/collection/${id}`,
);
const index = state.value.findIndex((e) => e.id == id); const index = state.value.findIndex((e) => e.id == id);
if (index == -1) { if (index == -1) {
state.value.push(collection); state.value.push(collection);
@@ -27,7 +29,7 @@ export async function refreshCollection(id: string) {
} }
export const useLibrary = async () => { export const useLibrary = async () => {
// @ts-expect-error // @ts-expect-error undefined is used to tell if value has been fetched or not
const state = useState<FullCollection>("library", () => undefined); const state = useState<FullCollection>("library", () => undefined);
if (state.value === undefined) { if (state.value === undefined) {
await refreshLibrary(); await refreshLibrary();
+1 -1
View File
@@ -31,7 +31,7 @@ export const fetchNews = async (options?: {
const news = useNews(); const news = useNews();
// @ts-ignore // @ts-ignore forget why this ignor exists
const newValue = await $dropFetch(`/api/v1/news?${query.toString()}`); const newValue = await $dropFetch(`/api/v1/news?${query.toString()}`);
news.value = newValue; news.value = newValue;
+3 -4
View File
@@ -1,5 +1,4 @@
import type { import type {
$Fetch,
ExtractedRouteMethod, ExtractedRouteMethod,
NitroFetchOptions, NitroFetchOptions,
NitroFetchRequest, NitroFetchRequest,
@@ -8,15 +7,15 @@ import type {
interface DropFetch< interface DropFetch<
DefaultT = unknown, DefaultT = unknown,
DefaultR extends NitroFetchRequest = NitroFetchRequest DefaultR extends NitroFetchRequest = NitroFetchRequest,
> { > {
< <
T = DefaultT, T = DefaultT,
R extends NitroFetchRequest = DefaultR, R extends NitroFetchRequest = DefaultR,
O extends NitroFetchOptions<R> = NitroFetchOptions<R> O extends NitroFetchOptions<R> = NitroFetchOptions<R>,
>( >(
request: R, request: R,
opts?: O opts?: O,
): Promise< ): Promise<
// @ts-ignore // @ts-ignore
TypedInternalResponse< TypedInternalResponse<
+5 -5
View File
@@ -34,7 +34,7 @@
autocomplete="username" autocomplete="username"
required required
class="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm bg-zinc-950/20 text-zinc-300 ring-1 ring-inset ring-zinc-800 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6" class="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm bg-zinc-950/20 text-zinc-300 ring-1 ring-inset ring-zinc-800 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
> />
</div> </div>
</div> </div>
@@ -53,7 +53,7 @@
autocomplete="current-password" autocomplete="current-password"
required required
class="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm bg-zinc-950/20 text-zinc-300 ring-1 ring-inset ring-zinc-800 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6" class="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm bg-zinc-950/20 text-zinc-300 ring-1 ring-inset ring-zinc-800 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
> />
</div> </div>
</div> </div>
@@ -65,7 +65,7 @@
name="remember-me" name="remember-me"
type="checkbox" type="checkbox"
class="h-4 w-4 rounded bg-zinc-800 border-zinc-700 text-blue-600 focus:ring-blue-600" class="h-4 w-4 rounded bg-zinc-800 border-zinc-700 text-blue-600 focus:ring-blue-600"
> />
<label <label
for="remember-me" for="remember-me"
class="ml-3 block text-sm leading-6 text-zinc-400" class="ml-3 block text-sm leading-6 text-zinc-400"
@@ -113,7 +113,7 @@
src="/wallpapers/signin.jpg" src="/wallpapers/signin.jpg"
class="absolute inset-0 h-full w-full object-cover" class="absolute inset-0 h-full w-full object-cover"
alt="" alt=""
> />
</div> </div>
</div> </div>
</template> </template>
@@ -121,7 +121,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { XCircleIcon } from "@heroicons/vue/20/solid"; import { XCircleIcon } from "@heroicons/vue/20/solid";
import type { User } from "@prisma/client"; import type { User } from "@prisma/client";
import Logo from "~/components/Logo.vue"; import Logo from "~/components/DropLogo.vue";
const username = ref(""); const username = ref("");
const password = ref(""); const password = ref("");
+2 -2
View File
@@ -22,13 +22,13 @@
src="/wallpapers/signin.jpg" src="/wallpapers/signin.jpg"
class="absolute inset-0 h-full w-full object-cover" class="absolute inset-0 h-full w-full object-cover"
alt="" alt=""
> />
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Logo from "~/components/Logo.vue"; import Logo from "~/components/DropLogo.vue";
const router = useRouter(); const router = useRouter();
// Clear the user state // Clear the user state
+1 -1
View File
@@ -70,9 +70,9 @@
class="whitespace-nowrap inline-flex gap-x-4 px-3 py-4 text-sm text-zinc-400" class="whitespace-nowrap inline-flex gap-x-4 px-3 py-4 text-sm text-zinc-400"
> >
<component <component
:is="PLATFORM_ICONS[platform]"
v-for="platform in platforms" v-for="platform in platforms"
:key="platform" :key="platform"
:is="PLATFORM_ICONS[platform]"
class="text-blue-600 w-6 h-6" class="text-blue-600 w-6 h-6"
/> />
<span <span
+1 -1
View File
@@ -1,6 +1,6 @@
import { APITokenMode } from "@prisma/client"; import { APITokenMode } from "@prisma/client";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { UserACL } from "~/server/internal/acls"; import type { UserACL } from "~/server/internal/acls";
import { defineClientEventHandler } from "~/server/internal/clients/event-handler"; import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
import prisma from "~/server/internal/db/database"; import prisma from "~/server/internal/db/database";