aboutsummaryrefslogtreecommitdiff
path: root/src/routes
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-01-02 21:47:28 -0800
committerFuwn <[email protected]>2024-01-02 21:47:28 -0800
commitc0e4dc886eaba03485ea4aaac37eaffb311aeb74 (patch)
tree70cbc8aa9fd46ee0eb3216e52e8c797e035cc747 /src/routes
parentfix(badges): datetime update (diff)
downloaddue.moe-c0e4dc886eaba03485ea4aaac37eaffb311aeb74.tar.xz
due.moe-c0e4dc886eaba03485ea4aaac37eaffb311aeb74.zip
feat(badges): categories
Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/api/badges/+server.ts31
-rw-r--r--src/routes/user/[user]/badges/+page.svelte102
2 files changed, 78 insertions, 55 deletions
diff --git a/src/routes/api/badges/+server.ts b/src/routes/api/badges/+server.ts
index fc5a4d0a..63e6ace4 100644
--- a/src/routes/api/badges/+server.ts
+++ b/src/routes/api/badges/+server.ts
@@ -49,41 +49,18 @@ export const PUT = async ({ cookies, url }) => {
post: url.searchParams.get('post') || undefined,
image: url.searchParams.get('image') || undefined,
description: url.searchParams.get('description') || undefined,
- time: url.searchParams.get('time') || undefined
+ time: url.searchParams.get('time') || undefined,
+ category: url.searchParams.get('category') || undefined
});
} else {
addUserBadge(identity.id, {
post: url.searchParams.get('post') || undefined,
image: url.searchParams.get('image') || undefined,
description: url.searchParams.get('description') || undefined,
- time: url.searchParams.get('time') || undefined
+ time: url.searchParams.get('time') || undefined,
+ category: url.searchParams.get('category') || undefined
});
}
return Response.json({});
};
-
-export const PATCH = async ({ cookies, url }) => {
- const userCookie = cookies.get('user');
-
- if (!userCookie) {
- return new Response('Unauthenticated', { status: 401 });
- }
-
- const user = JSON.parse(userCookie);
- const identity = await userIdentity({
- tokenType: user['token_type'],
- expiresIn: user['expires_in'],
- accessToken: user['access_token'],
- refreshToken: user['refresh_token']
- });
-
- updateUserBadge(identity.id, Number(url.searchParams.get('id')), {
- post: url.searchParams.get('post') || undefined,
- image: url.searchParams.get('image') || undefined,
- description: url.searchParams.get('description') || undefined,
- time: url.searchParams.get('time') || undefined
- });
-
- return Response.json({});
-};
diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte
index 20d4775a..69965e83 100644
--- a/src/routes/user/[user]/badges/+page.svelte
+++ b/src/routes/user/[user]/badges/+page.svelte
@@ -21,6 +21,8 @@
let confirmDelete = 0;
let selectedBadge: Badge | undefined = undefined;
+ type GroupedBadges = { [key: string]: Badge[] };
+
onMount(async () => {
// socket.on('badges', (message) => (badges = message));
@@ -45,6 +47,7 @@
const activityURL = document.querySelector('input[name="activity_url"]') as HTMLInputElement;
const description = document.querySelector('input[name="description"]') as HTMLInputElement;
const time = document.querySelector('input[type="datetime-local"]') as HTMLInputElement;
+ const category = document.querySelector('input[name="category"]') as HTMLInputElement;
if (!imageURL.value) {
error = 'Image URL cannot be empty.';
@@ -66,7 +69,7 @@
activityURL.value || '#'
)}${
description.value.length > 0 ? `&description=${encodeURIComponent(description.value)}` : ''
- }${
+ }${category.value.length > 0 ? `&category=${encodeURIComponent(category.value)}` : ''}${
time.valueAsDate ? `&time=${encodeURIComponent(dateToDatabaseTime(time.valueAsDate))}` : ''
}${
selectedBadge && selectedBadge.id ? `&update=${encodeURIComponent(selectedBadge.id)}` : ''
@@ -163,6 +166,26 @@
element.classList.remove('invert');
}
};
+
+ const groupBadges = (badges: Badge[]) => {
+ const groupedBadges: GroupedBadges = {};
+
+ badges.forEach((badge) => {
+ if (!badge.category) badge.category = 'Uncategorized';
+
+ if (!groupedBadges[badge.category]) groupedBadges[badge.category] = [];
+
+ groupedBadges[badge.category].push(badge);
+ });
+
+ return Object.entries(groupedBadges)
+ .sort((a, b) => b[1].length - a[1].length)
+ .reduce((set: GroupedBadges, [key, value]) => {
+ set[key] = value;
+
+ return set;
+ }, {});
+ };
</script>
<HeadTitle route={`${data.username}'s Badge Wall`} path={`/user/${data.username}`} />
@@ -227,6 +250,15 @@
size="11"
value={selectedBadge ? selectedBadge.description : ''}
/>
+ <input
+ type="text"
+ placeholder="Category (Optional)"
+ name="category"
+ minlength="1"
+ maxlength="1000"
+ size="11"
+ value={selectedBadge ? selectedBadge.category : ''}
+ />
<a href={`#`} on:click={submitBadge}>{selectedBadge ? 'Update' : 'Add'} Badge</a>
{#if selectedBadge}
or
@@ -253,36 +285,50 @@
{#if badgesResponse}
{#await badgesResponse.json()}
Loading badges ... 80%
- {:then badges}
+ {:then ungroupedBadges}
<div id="badges">
- {#if badges === null}
+ {#if ungroupedBadges === null}
{@html nbsp('Loading badges ... 50%')}
- {:else if badges.length === 0}
+ {:else if ungroupedBadges.length === 0}
{@html nbsp('No badges found for this user.')}
{:else}
- {#each badges as badge}
- {#if editMode}
- <a
- href={`#`}
- on:click={() => (selectedBadge = badge)}
- id={`badge-${badge.id}`}
- title={`${databaseTimeToDate(badge.time).toLocaleString()}${
- badge.description ? `\n${badge.description}` : ''
- }`}
- >
- <img src={badge.image} alt={badge.description} />
- </a>
- {:else}
- <a
- href={badge.post}
- target="_blank"
- id={`badge-${badge.id}`}
- title={`${databaseTimeToDate(badge.time).toLocaleString()}${
- badge.description ? `\n${badge.description}` : ''
- }`}
- >
- <img src={badge.image} alt={badge.description} />
- </a>
+ {@const groupedBadges = Object.entries(groupBadges(ungroupedBadges))}
+
+ {#each groupedBadges as [category, badges]}
+ <details open>
+ <summary>{category}</summary>
+
+ <div class="badges">
+ {#each badges as badge}
+ {#if editMode}
+ <a
+ href={`#`}
+ on:click={() => (selectedBadge = badge)}
+ id={`badge-${badge.id}`}
+ title={`${
+ badge.time ? databaseTimeToDate(badge.time).toLocaleString() : ''
+ }${badge.description ? `\n${badge.description}` : ''}`}
+ >
+ <img src={badge.image} alt={badge.description} />
+ </a>
+ {:else}
+ <a
+ href={badge.post}
+ target="_blank"
+ id={`badge-${badge.id}`}
+ title={`${
+ badge.time ? databaseTimeToDate(badge.time).toLocaleString() : ''
+ }${badge.description ? `\n${badge.description}` : ''}`}
+ >
+ <img src={badge.image} alt={badge.description} />
+ </a>
+ {/if}
+ {/each}
+ </div>
+ </details>
+
+ {#if groupedBadges[groupedBadges.length - 1][0] !== category}
+ <p />
{/if}
{/each}
{/if}
@@ -311,7 +357,7 @@
height: auto;
}
- #badges {
+ .badges {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(8%, 1fr));
grid-gap: 0.25%;