Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
899d77b
First iteration on the new PieChart component
Pacodastre Jul 31, 2025
ff15287
#128 Adds new admin home page
Pacodastre Oct 6, 2025
448110c
Fixes code after merging conflicts
Pacodastre Oct 7, 2025
9b765cb
Removes empty file
Pacodastre Oct 7, 2025
f00a18e
Uses real data for admin home page, and improves style
Pacodastre Oct 8, 2025
7ae14ab
Reverts debugging code
Pacodastre Oct 8, 2025
32172de
Defines missing variable
Pacodastre Oct 8, 2025
87d1a97
Caches user stats data for admin home page
Pacodastre Oct 8, 2025
bfe494c
Typo
Pacodastre Oct 13, 2025
a22910e
Styles improvements
Pacodastre Oct 13, 2025
df21a42
Invalidates cache on signup/signin
Pacodastre Oct 17, 2025
0299372
Implements top 5 biggest games
Pacodastre Oct 24, 2025
a52caa4
Improves styling
Pacodastre Oct 30, 2025
baac34a
Improves style
Pacodastre Oct 31, 2025
f64642a
Using generateManifest to get the proper size
Pacodastre Oct 31, 2025
bd970c6
Reading data from cache
Pacodastre Nov 2, 2025
40fad99
Removes unnecessary import
Pacodastre Nov 2, 2025
3bedfd1
Improves caching mechanism for game sizes
Pacodastre Nov 3, 2025
f6ba9fc
Removes lint errors
Pacodastre Nov 3, 2025
1f446be
Replaces piechart tooltip with colors in legend
Pacodastre Nov 3, 2025
0c33de0
Fixes caching
Pacodastre Nov 3, 2025
2a34202
Fixes caching and slight improvement on pie chart colours
Pacodastre Nov 3, 2025
49d834d
Fixes a few bugs related to caching
Pacodastre Nov 3, 2025
fb48f70
Fixes bug where app signin didn't refresh cache
Pacodastre Nov 3, 2025
6fa68a1
feat: style improvements
DecDuck Nov 7, 2025
7ac6b92
fix: lint
DecDuck Nov 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion components/GameEditor/Metadata.vue
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,6 @@ function coreMetadataUpdate_wrapper() {
);
})
.then((newGame) => {
console.log(newGame);
if (!newGame) return;
Object.assign(game.value, newGame);
coreMetadataIconUrl.value = useObject(newGame.mIconObjectId);
Expand Down
18 changes: 14 additions & 4 deletions components/GameEditor/Version.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@
@update="() => updateVersionOrder()"
>
<template
#item="{ element: item }: { element: GameVersionModel }"
#item="{ element: item }: { element: GameVersionModelWithSize }"
>
<div
class="w-full inline-flex items-center px-4 py-2 bg-zinc-800 rounded justify-between"
class="w-full inline-flex items-center px-4 py-2 bg-zinc-800 rounded justify-between w-full flex"
>
<div class="text-zinc-100 font-semibold">
<div class="text-zinc-100 font-semibold flex-none">
{{ item.versionName }}
</div>
<div
class="text-right text-zinc-400 text-xs font-normal flex-auto pr-4"
>
{{ item.size && formatBytes(item.size) }}
</div>
<div class="text-zinc-400">
{{ item.delta ? $t("library.admin.version.delta") : "" }}
</div>
Expand Down Expand Up @@ -117,6 +122,7 @@ import { Bars3Icon, TrashIcon } from "@heroicons/vue/24/solid";
import type { SerializeObject } from "nitropack";
import type { H3Error } from "h3";
import { ExclamationCircleIcon } from "@heroicons/vue/24/outline";
import { formatBytes } from "~/server/internal/utils/files";

// TODO implement UI for this page

Expand All @@ -130,7 +136,11 @@ const canImport = computed(
() => hasDeleted.value || props.unimportedVersions.length > 0,
);

type GameAndVersions = GameModel & { versions: GameVersionModel[] };
type GameVersionModelWithSize = GameVersionModel & { size: number };

type GameAndVersions = GameModel & {
versions: GameVersionModelWithSize[];
};
const game = defineModel<SerializeObject<GameAndVersions>>() as Ref<
SerializeObject<GameAndVersions>
>;
Expand Down
19 changes: 19 additions & 0 deletions components/Icons/GamepadIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="6" y1="11" x2="10" y2="11" />
<line x1="8" y1="9" x2="8" y2="13" />
<line x1="15" y1="12" x2="15.01" y2="12" />
<line x1="18" y1="10" x2="18.01" y2="10" />
<path
d="M17.32 5H6.68a4 4 0 00-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 003 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 019.828 16h4.344a2 2 0 011.414.586L17 18c.5.5 1 1 2 1a3 3 0 003-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0017.32 5z"
/>
</svg>
</template>
45 changes: 45 additions & 0 deletions components/PieChart/PieChart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<h2 v-if="title" class="text-lg mb-4 w-full">{{ title }}</h2>
<div class="flex flex-col xl:flex-row gap-4">
<div class="relative flex grow max-w-[12rem]">
<svg class="aspect-square grow relative inline" viewBox="0 0 100 100">
<PieChartPieSlice
v-for="slice in slices"
:key="`${slice.percentage}-${slice.totalPercentage}`"
:slice="slice"
/>
</svg>
<div class="absolute inset-0 bg-zinc-900 rounded-full m-12" />
</div>
<ul class="flex flex-col gap-y-1 justify-center text-left">
<li
v-for="slice in slices"
:key="slice.value"
class="text-sm inline-flex items-center gap-x-1"
>
<span
class="size-3 inline-block rounded-sm"
:class="CHART_COLOURS[slice.color].bg"
/>
{{
$t("common.labelValueColon", {
label: slice.label,
value: slice.value,
})
}}
</li>
</ul>
</div>
</template>

<script setup lang="ts">
import { generateSlices } from "~/components/PieChart/utils";
import type { SliceData } from "~/components/PieChart/types";

const { data, title = undefined } = defineProps<{
data: SliceData[];
title?: string | undefined;
}>();

const slices = generateSlices(data);
</script>
35 changes: 35 additions & 0 deletions components/PieChart/PieSlice.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<path
v-if="slice.percentage !== 0 && slice.percentage !== 100"
:class="[CHART_COLOURS[slice.color].fill]"
:d="`
M ${slice.start}
A ${slice.radius},${slice.radius} 0 ${getFlags(slice.percentage)} ${polarToCartesian(slice.center, slice.radius, percent2Degrees(slice.totalPercentage))}
L ${slice.center}
z
`"
stroke-width="2"
/>
<circle
v-if="slice.percentage === 100"
:r="slice.radius"
:cx="slice.center.x"
:cy="slice.center.y"
:class="[CHART_COLOURS[slice.color].fill]"
stroke-width="2"
/>
</template>

<script setup lang="ts">
import type { Slice } from "~/components/PieChart/types";
import {
getFlags,
percent2Degrees,
polarToCartesian,
} from "~/components/PieChart/utils";
import { CHART_COLOURS } from "~/utils/colors";

const { slice } = defineProps<{
slice: Slice;
}>();
</script>
19 changes: 19 additions & 0 deletions components/PieChart/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type Tuple from "~/utils/tuple";
import type { ChartColour } from "~/utils/colors";

export type Slice = {
start: Tuple;
center: Tuple;
percentage: number;
totalPercentage: number;
radius: number;
color: ChartColour;
label: string;
value: number;
};

export type SliceData = {
value: number;
color?: ChartColour;
label: string;
};
50 changes: 50 additions & 0 deletions components/PieChart/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Tuple from "~/utils/tuple";
import type { Slice, SliceData } from "~/components/PieChart/types";
import { sum, lastItem } from "~/utils/array";

export const START = new Tuple(50, 10);
export const CENTER = new Tuple(50, 50);
export const RADIUS = 40;

export const polarToCartesian = (
center: Tuple,
radius: number,
angleInDegrees: number,
) => {
const angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180;
const x = center.x + radius * Math.cos(angleInRadians);
const y = center.y + radius * Math.sin(angleInRadians);
return new Tuple(x, y);
};

export const percent2Degrees = (percentage: number) => (360 * percentage) / 100;

export function generateSlices(data: SliceData[]): Slice[] {
return data.reduce((accumulator, currentValue, index, array) => {
const percentage =
(currentValue.value * 100) / sum(array.map((slice) => slice.value));
return [
...accumulator,
{
start: accumulator.length
? polarToCartesian(
CENTER,
RADIUS,
percent2Degrees(lastItem(accumulator).totalPercentage),
)
: START,
radius: RADIUS,
percentage: percentage,
totalPercentage:
sum(accumulator.map((element) => element.percentage)) + percentage,
center: CENTER,
color: PIE_COLOURS[index % PIE_COLOURS.length],
label: currentValue.label,
value: currentValue.value,
},
];
}, [] as Slice[]);
}

export const getFlags = (percentage: number) =>
percentage > 50 ? new Tuple(1, 1) : new Tuple(0, 1);
31 changes: 31 additions & 0 deletions components/ProgressBar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<div
:class="[
'relative h-5 rounded-xl overflow-hidden',
CHART_COLOURS[backgroundColor].bg,
]"
>
<div
:style="{ width: `${percentage}%` }"
:class="['transition-all h-full', CHART_COLOURS[color].bg]"
/>
<span
class="absolute inset-0 flex items-center justify-center text-blue-200 text-sm font-bold font-display"
>
{{ $t("tasks.admin.progress", [Math.round(percentage * 10) / 10]) }}
</span>
</div>
</template>

<script setup lang="ts">
import { type ChartColour, CHART_COLOURS } from "~/utils/colors";
const {
percentage,
color = "blue",
backgroundColor = "zinc",
} = defineProps<{
percentage: number;
color?: ChartColour;
backgroundColor?: ChartColour;
}>();
</script>
43 changes: 43 additions & 0 deletions components/RankingList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<table v-if="items.length > 0" class="w-full mt-4 space-y-6">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody class="divide-y divide-white/10">
<tr v-for="item in items" :key="`${item.rank}-${item.name}`">
<td
class="my-2 size-7 rounded-sm bg-zinc-950 ring ring-zinc-800 inline-flex items-center justify-center font-bold font-display text-blue-500"
>
{{ item.rank }}
</td>
<td class="w-full font-bold px-2">{{ item.name }}</td>
<td
class="text-right text-sm font-semibold text-zinc-500 whitespace-nowrap"
>
{{ item.value }}
</td>
</tr>
</tbody>
</table>
<p
v-else
class="w-full p-2 text-center uppercase text-sm font-display font-bold text-zinc-700"
>
{{ $t("common.noData") }}
</p>
</template>

<script lang="ts" setup>
export type RankItem = {
rank: number;
name: string;
value: string;
};
const { items } = defineProps<{
items: RankItem[];
}>();
</script>
Loading