mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-14 16:51:15 +10:00
feat: add user platform filters to store view
This commit is contained in:
26
components/Icons/Platform.vue
Normal file
26
components/Icons/Platform.vue
Normal 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>
|
||||||
@ -247,7 +247,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(option, optionIdx) in section.options"
|
v-for="(option, optionIdx) in section.options"
|
||||||
:key="option.param"
|
:key="option.param"
|
||||||
class="flex gap-3"
|
class="flex items-center gap-3"
|
||||||
>
|
>
|
||||||
<div class="flex h-5 shrink-0 items-center">
|
<div class="flex h-5 shrink-0 items-center">
|
||||||
<div class="group grid size-4 grid-cols-1">
|
<div class="group grid size-4 grid-cols-1">
|
||||||
@ -272,6 +272,12 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<IconsPlatform
|
||||||
|
v-if="option.platformIcon"
|
||||||
|
:platform="option.platformIcon.key"
|
||||||
|
:fallback="option.platformIcon.fallback"
|
||||||
|
class="size-5 text-blue-500"
|
||||||
|
/>
|
||||||
<label
|
<label
|
||||||
:for="`filter-${section.param}-${optionIdx}`"
|
:for="`filter-${section.param}-${optionIdx}`"
|
||||||
class="text-sm text-zinc-400"
|
class="text-sm text-zinc-400"
|
||||||
@ -411,8 +417,16 @@ const options: Array<StoreFilterOption> = [
|
|||||||
param: "platform",
|
param: "platform",
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: [
|
options: [
|
||||||
...Object.values(Platform).map((e) => ({ name: e, param: e })),
|
...Object.values(Platform).map((e) => ({
|
||||||
...userPlatforms.map((e) => ({ name: e.platformName, param: e.id })),
|
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 ?? []),
|
...(props.extraOptions ?? []),
|
||||||
|
|||||||
@ -8,4 +8,5 @@ export type StoreFilterOption = {
|
|||||||
export type StoreSortOption = {
|
export type StoreSortOption = {
|
||||||
name: string;
|
name: string;
|
||||||
param: string;
|
param: string;
|
||||||
|
platformIcon?: { key: string; fallback?: string };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -73,18 +73,18 @@
|
|||||||
<td
|
<td
|
||||||
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"
|
||||||
>
|
>
|
||||||
<div
|
<IconsPlatform
|
||||||
v-for="platform in platforms"
|
v-for="platform in platforms"
|
||||||
:key="typeof platform === 'string' ? platform : platform.id"
|
:key="typeof platform === 'string' ? platform : platform.id"
|
||||||
>
|
:platform="
|
||||||
<component
|
typeof platform === 'string' ? platform : platform.id
|
||||||
:is="PLATFORM_ICONS[platform]"
|
"
|
||||||
v-if="typeof platform === 'string'"
|
:fallback="
|
||||||
class="text-blue-600 w-6 h-6"
|
typeof platform === 'string'
|
||||||
/>
|
? undefined
|
||||||
<div v-else class="text-blue-600 w-6 h-6" v-html="platform.iconSvg" />
|
: platform.iconSvg
|
||||||
</div>
|
"
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
v-if="platforms.length == 0"
|
v-if="platforms.length == 0"
|
||||||
class="font-display uppercase font-bold text-zinc-700"
|
class="font-display uppercase font-bold text-zinc-700"
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export default defineEventHandler(async (h3) => {
|
|||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
platformName: true,
|
platformName: true,
|
||||||
|
iconSvg: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return platforms;
|
return platforms;
|
||||||
|
|||||||
Reference in New Issue
Block a user