From 622abc915534e4999c25766cb7ba33f2eb1f0ef6 Mon Sep 17 00:00:00 2001
From: JustTemmie <47639983+JustTemmie@users.noreply.github.com>
Date: Sun, 1 Jun 2025 19:24:50 +0200
Subject: [PATCH] feat: profile page, EXCEPT FUCKING AVATARS AAAAAHHH
---
components/Userpopup.vue | 48 ++++----
components/buttons/Button.vue | 6 +-
components/buttons/ButtonScary.vue | 6 +-
components/settings/user_settings/Account.vue | 115 +++++++++++++++++-
composables/auth.ts | 1 -
pages/settings.vue | 9 +-
types/interfaces.ts | 3 +-
7 files changed, 148 insertions(+), 40 deletions(-)
diff --git a/components/Userpopup.vue b/components/Userpopup.vue
index 1e90026..7381637 100644
--- a/components/Userpopup.vue
+++ b/components/Userpopup.vue
@@ -3,8 +3,12 @@
-
{{ props.user.display_name || "display_name" }}
-
{{ props.user.username || "username" }}
+
+ {{ props.user.display_name || "display_name" }}
+
+
+ {{ props.user.username || "username" }} - {{ props.user.pronouns || "un/defined" }}
+
About me
@@ -18,15 +22,15 @@ import type { UserResponse } from '~/types/interfaces';
const { fetchMembers } = useApi();
const props = defineProps<{
- user: UserResponse,
+ user: UserResponse | any, // actually UserResponse | null but TS is yelling at me again
}>();
\ No newline at end of file
diff --git a/components/buttons/Button.vue b/components/buttons/Button.vue
index 20783c0..2544fbb 100644
--- a/components/buttons/Button.vue
+++ b/components/buttons/Button.vue
@@ -28,11 +28,11 @@ const props = defineProps<{
background-color: #b35719;
color: #ffffff;
- padding: 8px 16px;
- font-size: 16px;
+ padding: 8px 18px;
+ font-size: 18px;
transition: background-color 0.2s;
- border-radius: 16px;
+ border-radius: 12px;
text-decoration: none;
display: inline-block;
}
diff --git a/components/buttons/ButtonScary.vue b/components/buttons/ButtonScary.vue
index 71c0bc7..1fa2c85 100644
--- a/components/buttons/ButtonScary.vue
+++ b/components/buttons/ButtonScary.vue
@@ -28,11 +28,11 @@ const props = defineProps<{
background-color: #f02f2f;
color: #ffffff;
- padding: 8px 16px;
- font-size: 16px;
+ padding: 8px 18px;
+ font-size: 18px;
transition: background-color 0.2s;
- border-radius: 16px;
+ border-radius: 12px;
text-decoration: none;
display: inline-block;
}
diff --git a/components/settings/user_settings/Account.vue b/components/settings/user_settings/Account.vue
index 9b7d044..74d120d 100644
--- a/components/settings/user_settings/Account.vue
+++ b/components/settings/user_settings/Account.vue
@@ -2,10 +2,31 @@
My Account
-
-
+
+
+
AVATAR
+
+
+
DISPLAY NAME
+
+
USERNAME
+
+
PRONOUNS
+
+
ABOUT ME
+
{{ user?.about_me || "TBD" }}
+
+
+
+
+
+
+
+
+
+
Password (and eventually authenticator)
@@ -19,10 +40,81 @@
import Button from '~/components/buttons/Button.vue';
import ButtonScary from '~/components/buttons/ButtonScary.vue';
-const { user, fetchUser } = useAuth();
+const { fetchUser } = useAuth();
const user_me = await fetchUser()
+let user_reference = Object.assign({}, user_me)
+const user = user_me!
+let new_pfp_file: any = null
+
+const saveChanges = async () => {
+ try {
+ const formData = new FormData()
+
+ if (new_pfp_file) {
+ formData.append('avatar', new_pfp_file, new_pfp_file.name)
+ new_pfp_file = null
+ }
+
+ // oh lord praise deep seek v3
+ const jsonBlob = new Blob(
+ [JSON.stringify({
+ display_name: user.display_name,
+ username: user.username,
+ pronouns: user.pronouns,
+ })],
+ { type: 'application/json' }
+ );
+ formData.append('json', jsonBlob, 'data.json');
+
+ await fetchWithApi("/me", {
+ method: "PATCH",
+ body: formData
+ })
+
+ user_reference = Object.assign({}, user_me)
+ alert("success!!")
+ } catch (error: any) {
+ if (error?.response?.status !== 200) {
+ const errorData = await error?.response?.json()
+
+ alert(`error ${error?.response?.status} met whilst trying to update profile info\n${errorData}`)
+ }
+ }
+};
+
+
+const removeAvatar = async () => {
+ alert("TBD")
+ // await fetchWithApi(`/auth/reset-password`);
+}
+
+const changeAvatar = async () => {
+ try {
+ let input = document.createElement('input');
+ input.type = 'file';
+ input.accept = 'image/*';
+
+ input.onchange = async(e) => {
+ const file = e.target.files?.[0];
+ if (!file) return;
+
+ new_pfp_file = file;
+
+ const reader = new FileReader();
+ reader.onload = (e) => {
+ user.avatar = e?.target?.result;
+ };
+ reader.readAsDataURL(file);
+ }
+
+ input.oncancel = () => alert("cancelled upload!");
+ input.click();
+ } catch (err) {
+ console.error('User canceled or error:', err);
+ }
+}
const resetPassword = async () => {
alert("TBD")
@@ -35,11 +127,24 @@ const deleteAccount = async () => {
\ No newline at end of file
diff --git a/composables/auth.ts b/composables/auth.ts
index 4ec2f32..0ac2e8b 100644
--- a/composables/auth.ts
+++ b/composables/auth.ts
@@ -76,7 +76,6 @@ export const useAuth = () => {
if (!accessToken.value) return;
console.log("fetchuser access token:", accessToken.value);
const res = await fetchWithApi("/me") as UserResponse;
- res.avatar = res.avatar ?? "https://gorb.b-cdn.net/avatar/default-pfp.png";
user.value = res;
return user.value;
}
diff --git a/pages/settings.vue b/pages/settings.vue
index 050c1f8..fb66aa2 100644
--- a/pages/settings.vue
+++ b/pages/settings.vue
@@ -115,8 +115,8 @@ const selectCategory = (_category: Category, page: Page) => {
}
#sidebar {
- min-width: 200px;
- max-width: 200px;
+ min-width: 250px;
+ max-width: 250px;
background-color: #2f3136;
color: white;
padding: 10px;
@@ -127,7 +127,7 @@ const selectCategory = (_category: Category, page: Page) => {
}
#sidebar h2 {
- font-size: 1.5em;
+ font-size: 2em;
padding: 0 8px;
}
@@ -140,6 +140,7 @@ const selectCategory = (_category: Category, page: Page) => {
#sidebar li {
border-radius: 8px;
padding: 8px;
+ font-size: 1.3em;
margin: 2px 0;
cursor: pointer;
transition: background-color 0.3s;
@@ -155,7 +156,7 @@ const selectCategory = (_category: Category, page: Page) => {
#sub_page {
flex-grow: 1;
- max-width: 600px;
+ max-width: 800px;
margin-left: 1.5rem;
margin-right: auto;
diff --git a/types/interfaces.ts b/types/interfaces.ts
index a0d7d39..04da39a 100644
--- a/types/interfaces.ts
+++ b/types/interfaces.ts
@@ -57,8 +57,9 @@ export interface UserResponse {
uuid: string,
username: string,
display_name: string | null,
- avatar: string,
+ avatar: string | null,
pronouns: string | null,
+ about_me: string | null,
email?: string,
email_verified?: boolean
}