feat: add user platform filters to store view

This commit is contained in:
DecDuck
2025-08-27 12:16:27 +10:00
parent 8efddc07bc
commit 367d349a68
5 changed files with 55 additions and 13 deletions

View File

@ -0,0 +1,26 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<component
:is="platformIcons[props.platform as Platform]"
v-if="platformIcons[props.platform as Platform]"
/>
<div v-else-if="props.fallback" v-html="props.fallback" />
<DropLogo v-else />
</template>
<script setup lang="ts">
import { Platform } from "~/prisma/client/enums";
import type { Component } from "vue";
import LinuxLogo from "./LinuxLogo.vue";
import WindowsLogo from "./WindowsLogo.vue";
import MacLogo from "./MacLogo.vue";
import DropLogo from "../DropLogo.vue";
const props = defineProps<{ platform: string; fallback?: string }>();
const platformIcons: { [key in Platform]: Component } = {
[Platform.Linux]: LinuxLogo,
[Platform.Windows]: WindowsLogo,
[Platform.macOS]: MacLogo,
};
</script>

View File

@ -247,7 +247,7 @@
<div
v-for="(option, optionIdx) in section.options"
:key="option.param"
class="flex gap-3"
class="flex items-center gap-3"
>
<div class="flex h-5 shrink-0 items-center">
<div class="group grid size-4 grid-cols-1">
@ -272,6 +272,12 @@
/>
</div>
</div>
<IconsPlatform
v-if="option.platformIcon"
:platform="option.platformIcon.key"
:fallback="option.platformIcon.fallback"
class="size-5 text-blue-500"
/>
<label
:for="`filter-${section.param}-${optionIdx}`"
class="text-sm text-zinc-400"
@ -411,8 +417,16 @@ const options: Array<StoreFilterOption> = [
param: "platform",
multiple: true,
options: [
...Object.values(Platform).map((e) => ({ name: e, param: e })),
...userPlatforms.map((e) => ({ name: e.platformName, param: e.id })),
...Object.values(Platform).map((e) => ({
name: e,
param: e,
platformIcon: { key: e },
})),
...userPlatforms.map((e) => ({
name: e.platformName,
param: e.id,
platformIcon: { key: e.id, fallback: e.iconSvg },
})),
],
},
...(props.extraOptions ?? []),

View File

@ -8,4 +8,5 @@ export type StoreFilterOption = {
export type StoreSortOption = {
name: string;
param: string;
platformIcon?: { key: string; fallback?: string };
};

View File

@ -73,18 +73,18 @@
<td
class="whitespace-nowrap inline-flex gap-x-4 px-3 py-4 text-sm text-zinc-400"
>
<div
<IconsPlatform
v-for="platform in platforms"
:key="typeof platform === 'string' ? platform : platform.id"
>
<component
:is="PLATFORM_ICONS[platform]"
v-if="typeof platform === 'string'"
class="text-blue-600 w-6 h-6"
/>
<div v-else class="text-blue-600 w-6 h-6" v-html="platform.iconSvg" />
</div>
:platform="
typeof platform === 'string' ? platform : platform.id
"
:fallback="
typeof platform === 'string'
? undefined
: platform.iconSvg
"
/>
<span
v-if="platforms.length == 0"
class="font-display uppercase font-bold text-zinc-700"

View File

@ -10,6 +10,7 @@ export default defineEventHandler(async (h3) => {
select: {
id: true,
platformName: true,
iconSvg: true,
},
});
return platforms;