feat: medal server card
This commit is contained in:
parent
d1a478dbf2
commit
2da2b4aec7
@ -0,0 +1,12 @@
|
|||||||
|
<svg viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="72" height="72" rx="12" fill="currentColor" fill-opacity="0.12" />
|
||||||
|
<path
|
||||||
|
d="M22.562 46.8959L31.189 42.2804C31.8922 41.9026 31.8873 40.9333 31.1763 40.558L22.426 35.9147C21.8463 35.6082 21.1377 36.0016 21.1373 36.6321L21.1319 46.0958C21.1315 46.7967 21.9244 47.2404 22.562 46.8985L22.562 46.8959Z"
|
||||||
|
fill="currentColor" />
|
||||||
|
<path
|
||||||
|
d="M48.7804 47.0911L40.1588 42.3472C39.4561 41.9589 39.4621 40.9896 40.1735 40.625L48.9288 36.112C49.5092 35.8141 50.2172 36.218 50.2168 36.8485L50.2114 46.3122C50.211 47.0131 49.4178 47.445 48.7804 47.0937L48.7804 47.0911Z"
|
||||||
|
fill="currentColor" />
|
||||||
|
<path
|
||||||
|
d="M62.1735 23.588L54.919 19.3778C54.3937 19.0742 53.7374 19.0615 53.2066 19.3468L36.5152 28.3219C35.9844 28.6072 35.3333 28.6024 34.8028 28.3092L18.1193 19.0882C17.5888 18.7951 16.9323 18.7954 16.4069 19.0937L9.14477 23.1933C8.62214 23.4891 8.30179 24.0235 8.30145 24.6046L8.29042 43.8064C8.2901 44.3589 8.58797 44.877 9.07744 45.1777L15.2929 48.9763C15.4214 49.0554 15.6784 49.2085 15.971 49.3853C16.5917 49.7573 17.3935 49.3359 17.3884 48.6401C17.3886 48.3431 17.3887 48.0721 17.3888 47.9053L17.4315 30.8117C17.432 29.9049 18.4636 29.3471 19.2894 29.8041L34.7506 38.3879C35.3084 38.697 35.9922 38.7021 36.5477 38.4013L52.0186 30.0477C52.845 29.603 53.8731 30.1762 53.8753 31.083L53.8983 48.177C53.8982 48.3282 53.9008 48.6044 53.9033 48.9171C53.9084 49.6077 54.707 50.0358 55.3225 49.6729C55.599 49.5108 55.8509 49.3642 55.9931 49.2792L62.2128 45.5732C62.7025 45.2798 63.0011 44.7687 63.0014 44.2137L63.0125 25.0118C63.0128 24.4307 62.693 23.8889 62.1707 23.588L62.1735 23.588Z"
|
||||||
|
fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
167
apps/frontend/src/components/ui/servers/MedalServerListing.vue
Normal file
167
apps/frontend/src/components/ui/servers/MedalServerListing.vue
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<NuxtLink
|
||||||
|
class="contents"
|
||||||
|
:to="status === 'suspended' ? '' : `/servers/manage/${props.server_id}`"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="medal-promotion flex flex-row items-center overflow-x-hidden rounded-2xl p-4 shadow-xl transition-transform duration-100"
|
||||||
|
:class="status === 'suspended' ? '!rounded-b-none border-b-0 opacity-75' : 'active:scale-95'"
|
||||||
|
data-pyro-server-listing
|
||||||
|
:data-pyro-server-listing-id="server_id"
|
||||||
|
>
|
||||||
|
<div class="overlay"></div>
|
||||||
|
<MedalPromoBackground class="background-pattern" />
|
||||||
|
<MedalServerIcon
|
||||||
|
v-if="status !== 'suspended'"
|
||||||
|
class="z-10 size-16 rounded-xl bg-bg text-orange"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="bg-bg-secondary z-10 flex size-16 items-center justify-center rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
|
||||||
|
>
|
||||||
|
<LockIcon class="size-12 text-secondary" />
|
||||||
|
</div>
|
||||||
|
<div class="z-10 ml-4 flex flex-col gap-2.5">
|
||||||
|
<div class="flex flex-row items-center gap-2">
|
||||||
|
<h2 class="m-0 text-xl font-bold text-contrast">{{ name }}</h2>
|
||||||
|
<ChevronRightIcon />
|
||||||
|
|
||||||
|
<span>{{ timeLeftCountdown }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="projectData?.title"
|
||||||
|
class="m-0 flex flex-row items-center gap-2 text-sm font-medium text-secondary"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
:src="iconUrl"
|
||||||
|
no-shadow
|
||||||
|
style="min-height: 20px; min-width: 20px; height: 20px; width: 20px"
|
||||||
|
alt="Server Icon"
|
||||||
|
/>
|
||||||
|
Using {{ projectData?.title || "Unknown" }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="isConfiguring"
|
||||||
|
class="flex min-w-0 items-center gap-2 truncate text-sm font-semibold text-brand"
|
||||||
|
>
|
||||||
|
<SparklesIcon class="size-5 shrink-0" /> New server
|
||||||
|
</div>
|
||||||
|
<UiServersServerInfoLabels
|
||||||
|
v-else
|
||||||
|
:server-data="{ game, mc_version, loader, loader_version, net }"
|
||||||
|
:show-game-label="showGameLabel"
|
||||||
|
:show-loader-label="showLoaderLabel"
|
||||||
|
:linked="false"
|
||||||
|
class="pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-secondary *:hidden sm:flex-row sm:*:flex"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="status === 'suspended' && suspension_reason === 'upgrading'"
|
||||||
|
class="relative -mt-4 flex w-full flex-row items-center gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-blue bg-bg-blue p-4 text-sm font-bold text-contrast"
|
||||||
|
>
|
||||||
|
<UiServersPanelSpinner />
|
||||||
|
Your server's hardware is currently being upgraded and will be back online shortly.
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="status === 'suspended' && suspension_reason === 'cancelled'"
|
||||||
|
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||||
|
>
|
||||||
|
<div class="flex flex-row gap-2">
|
||||||
|
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been cancelled. Please
|
||||||
|
update your billing information or contact Modrinth Support for more information.
|
||||||
|
</div>
|
||||||
|
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="status === 'suspended' && suspension_reason"
|
||||||
|
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||||
|
>
|
||||||
|
<div class="flex flex-row gap-2">
|
||||||
|
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been suspended:
|
||||||
|
{{ suspension_reason }}. Please update your billing information or contact Modrinth Support
|
||||||
|
for more information.
|
||||||
|
</div>
|
||||||
|
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="status === 'suspended'"
|
||||||
|
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||||
|
>
|
||||||
|
<div class="flex flex-row gap-2">
|
||||||
|
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been suspended. Please
|
||||||
|
update your billing information or contact Modrinth Support for more information.
|
||||||
|
</div>
|
||||||
|
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
|
||||||
|
</div>
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ChevronRightIcon, LockIcon, SparklesIcon } from "@modrinth/assets";
|
||||||
|
import type { Project, Server } from "@modrinth/utils";
|
||||||
|
import { Avatar, CopyCode } from "@modrinth/ui";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import MedalServerIcon from "~/assets/images/servers/medal_server_icon.svg?component";
|
||||||
|
import MedalPromoBackground from "~/assets/images/illustrations/medal_promo_background.svg?component";
|
||||||
|
|
||||||
|
const props = defineProps<Partial<Server>>();
|
||||||
|
|
||||||
|
const showGameLabel = computed(() => !!props.game);
|
||||||
|
const showLoaderLabel = computed(() => !!props.loader);
|
||||||
|
|
||||||
|
let projectData: Ref<Project | null>;
|
||||||
|
if (props.upstream) {
|
||||||
|
const { data } = await useAsyncData<Project>(
|
||||||
|
`server-project-${props.server_id}`,
|
||||||
|
async (): Promise<Project> => {
|
||||||
|
const result = await useBaseFetch(`project/${props.upstream?.project_id}`);
|
||||||
|
return result as Project;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
projectData = data;
|
||||||
|
} else {
|
||||||
|
projectData = ref(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconUrl = computed(() => projectData.value?.icon_url || undefined);
|
||||||
|
const isConfiguring = computed(() => props.flows?.intro);
|
||||||
|
|
||||||
|
const expiryDate = dayjs().add(5, "day");
|
||||||
|
const timeLeftCountdown = computed(() => {
|
||||||
|
const now = dayjs();
|
||||||
|
const diff = expiryDate.diff(now, "day");
|
||||||
|
return diff > 0 ? `${diff} day${diff > 1 ? "s" : ""} left` : "Expired";
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.medal-promotion {
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid var(--color-orange);
|
||||||
|
background: inherit; // allows overlay + pattern to take over
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent 50%, var(--landing-raw-bg) 100%);
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.background-pattern {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 0;
|
||||||
|
background-color: var(--landing-raw-bg);
|
||||||
|
border-radius: inherit;
|
||||||
|
color: var(--color-orange);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="experimental-styles-within flex size-24 shrink-0 overflow-hidden rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
|
class="experimental-styles-within flex size-16 shrink-0 overflow-hidden rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
|
||||||
>
|
>
|
||||||
<client-only>
|
<client-only>
|
||||||
<img
|
<img
|
||||||
|
|||||||
@ -4,26 +4,19 @@
|
|||||||
:to="status === 'suspended' ? '' : `/servers/manage/${props.server_id}`"
|
:to="status === 'suspended' ? '' : `/servers/manage/${props.server_id}`"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-tooltip="
|
class="flex flex-row items-center overflow-x-hidden rounded-2xl border-[1px] border-solid border-button-bg bg-bg-raised p-4 transition-transform duration-100"
|
||||||
status === 'suspended'
|
:class="status === 'suspended' ? '!rounded-b-none border-b-0 opacity-75' : 'active:scale-95'"
|
||||||
? suspension_reason === 'upgrading'
|
|
||||||
? 'This server is being transferred to a new node. It will be unavailable until this process finishes.'
|
|
||||||
: 'This server has been suspended. Please visit your billing settings or contact Modrinth Support for more information.'
|
|
||||||
: ''
|
|
||||||
"
|
|
||||||
class="flex cursor-pointer flex-row items-center overflow-x-hidden rounded-3xl bg-bg-raised p-4 transition-transform duration-100"
|
|
||||||
:class="status === 'suspended' ? '!rounded-b-none opacity-75' : 'active:scale-95'"
|
|
||||||
data-pyro-server-listing
|
data-pyro-server-listing
|
||||||
:data-pyro-server-listing-id="server_id"
|
:data-pyro-server-listing-id="server_id"
|
||||||
>
|
>
|
||||||
<UiServersServerIcon v-if="status !== 'suspended'" :image="image" />
|
<UiServersServerIcon v-if="status !== 'suspended'" :image="image" />
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="bg-bg-secondary flex size-24 items-center justify-center rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
|
class="bg-bg-secondary flex size-16 items-center justify-center rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
|
||||||
>
|
>
|
||||||
<LockIcon class="size-20 text-secondary" />
|
<LockIcon class="size-12 text-secondary" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-8 flex flex-col gap-2.5">
|
<div class="ml-4 flex flex-col gap-2.5">
|
||||||
<div class="flex flex-row items-center gap-2">
|
<div class="flex flex-row items-center gap-2">
|
||||||
<h2 class="m-0 text-xl font-bold text-contrast">{{ name }}</h2>
|
<h2 class="m-0 text-xl font-bold text-contrast">{{ name }}</h2>
|
||||||
<ChevronRightIcon />
|
<ChevronRightIcon />
|
||||||
@ -41,7 +34,6 @@
|
|||||||
/>
|
/>
|
||||||
Using {{ projectData?.title || "Unknown" }}
|
Using {{ projectData?.title || "Unknown" }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="min-h-[20px]"></div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="isConfiguring"
|
v-if="isConfiguring"
|
||||||
@ -61,14 +53,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="status === 'suspended' && suspension_reason === 'upgrading'"
|
v-if="status === 'suspended' && suspension_reason === 'upgrading'"
|
||||||
class="relative -mt-4 flex w-full flex-row items-center gap-2 rounded-b-3xl bg-bg-blue p-4 text-sm font-bold text-contrast"
|
class="relative -mt-4 flex w-full flex-row items-center gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-blue bg-bg-blue p-4 text-sm font-bold text-contrast"
|
||||||
>
|
>
|
||||||
<UiServersPanelSpinner />
|
<UiServersPanelSpinner />
|
||||||
Your server's hardware is currently being upgraded and will be back online shortly.
|
Your server's hardware is currently being upgraded and will be back online shortly.
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="status === 'suspended' && suspension_reason === 'cancelled'"
|
v-else-if="status === 'suspended' && suspension_reason === 'cancelled'"
|
||||||
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
|
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||||
>
|
>
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been cancelled. Please
|
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been cancelled. Please
|
||||||
@ -78,7 +70,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="status === 'suspended' && suspension_reason"
|
v-else-if="status === 'suspended' && suspension_reason"
|
||||||
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
|
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||||
>
|
>
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been suspended:
|
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been suspended:
|
||||||
@ -89,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="status === 'suspended'"
|
v-else-if="status === 'suspended'"
|
||||||
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
|
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||||
>
|
>
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been suspended. Please
|
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been suspended. Please
|
||||||
@ -103,8 +95,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ChevronRightIcon, LockIcon, SparklesIcon } from "@modrinth/assets";
|
import { ChevronRightIcon, LockIcon, SparklesIcon } from "@modrinth/assets";
|
||||||
import type { Project, Server } from "@modrinth/utils";
|
import type { Project, Server } from "@modrinth/utils";
|
||||||
import { useModrinthServers } from "~/composables/servers/modrinth-servers.ts";
|
|
||||||
import { Avatar, CopyCode } from "@modrinth/ui";
|
import { Avatar, CopyCode } from "@modrinth/ui";
|
||||||
|
import { useModrinthServers } from "~/composables/servers/modrinth-servers.ts";
|
||||||
|
|
||||||
const props = defineProps<Partial<Server>>();
|
const props = defineProps<Partial<Server>>();
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,12 @@
|
|||||||
class="m-0 flex flex-col gap-4 p-0"
|
class="m-0 flex flex-col gap-4 p-0"
|
||||||
>
|
>
|
||||||
<UiServersServerListing
|
<UiServersServerListing
|
||||||
v-for="server in filteredData"
|
v-for="server in filteredData.filter((s) => !s.is_preview)"
|
||||||
|
:key="server.server_id"
|
||||||
|
v-bind="server"
|
||||||
|
/>
|
||||||
|
<MedalServerListing
|
||||||
|
v-for="server in filteredData.filter((s) => s.status !== 'suspended')"
|
||||||
:key="server.server_id"
|
:key="server.server_id"
|
||||||
v-bind="server"
|
v-bind="server"
|
||||||
/>
|
/>
|
||||||
@ -115,6 +120,7 @@ import { ButtonStyled, CopyCode } from "@modrinth/ui";
|
|||||||
import type { Server, ModrinthServersFetchError } from "@modrinth/utils";
|
import type { Server, ModrinthServersFetchError } from "@modrinth/utils";
|
||||||
import { reloadNuxtApp } from "#app";
|
import { reloadNuxtApp } from "#app";
|
||||||
import { useServersFetch } from "~/composables/servers/servers-fetch.ts";
|
import { useServersFetch } from "~/composables/servers/servers-fetch.ts";
|
||||||
|
import MedalServerListing from "~/components/ui/servers/MedalServerListing.vue";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: "auth",
|
middleware: "auth",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user