Skip to content

Commit

Permalink
enhanced ProfileInformation Component and introduces user state
Browse files Browse the repository at this point in the history
  • Loading branch information
Likqez committed Dec 8, 2024
1 parent 33d7fe9 commit e48df28
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 31 deletions.
47 changes: 19 additions & 28 deletions components/profile/ProfileInformation.vue
Original file line number Diff line number Diff line change
@@ -1,42 +1,33 @@
<script setup lang="ts">
import type {
GetProfileResponse
} from "@/types/api/user";
const username = ref('Username');
const profilePicture = ref('https://t4.ftcdn.net/jpg/05/49/98/39/360_F_549983970_bRCkYfk0P6PP5fKbMhZMIb07mCJ6esXL.jpg');
const session = useSupabaseSession()
const {user, loading, error, fetchUser} = useUser()
onMounted(async () => {
if (session.value) {
await getProfileInformation()
}
if (session.value) {
await fetchUser()
console.log(user.value)
}
})
async function getProfileInformation() {
$fetch<GetProfileResponse>('http://localhost:3000/api/v1/user/' + session.value?.user.id) //TODO: change after implementing diffrent user endpoint. also add as global state wit useState named 'user'
.then((data) => {
username.value = data.username
if (data.user_avatar) {
profilePicture.value = data.user_avatar;
}
});
}
const default_avatar = ref('https://t4.ftcdn.net/jpg/05/49/98/39/360_F_549983970_bRCkYfk0P6PP5fKbMhZMIb07mCJ6esXL.jpg');
</script>

<template>
<div>
<div v-if="error" class="text-red-500">Error occurred: {{error}}</div>
<div class="flex flex-col">
<div class="flex flex-col items-center justify-center mb-3">
<NuxtImg :src="profilePicture" class="w-16 h-16 rounded-full" />
<p>{{ username }}</p>
</div>
<div class="flex flex-col items-center justify-center mb-3">
<NuxtImg :src="loading || !user?.avatar_url ? default_avatar : user!.avatar_url" class="w-16 h-16 rounded-full"/>
<p>{{ loading ? 'Loading.' : user?.username }}</p>
</div>

<div class="grid grid-cols-2 gap-4">
<div class="bg-gray-200 h-8 rounded-3xl px-3">Streak</div>
<div class="bg-gray-200 h-8 rounded-3xl px-3">Games played</div>
<div class="bg-gray-200 h-8 rounded-3xl px-3">Placeholder</div>
<div class="bg-gray-200 h-8 rounded-3xl px-3">Date joined</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div class="bg-gray-200 h-8 rounded-3xl px-3">Games played</div>
<div class="bg-gray-200 h-8 rounded-3xl px-3">Streak: {{ user?.daily_streak }}</div>
<div class="bg-gray-200 h-8 rounded-3xl px-3">Spotify {{user?.spotify_visibility ? 'public' : 'private'}}</div>
<div class="bg-gray-200 h-8 rounded-3xl px-3">Joined {{ new Date(session?.user.created_at).toDateString() }}</div>
</div>
</div>
</div>
</template>
34 changes: 34 additions & 0 deletions composables/useUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type {GetUserResponse} from "@/types/api/users";

export const useUser = () => {
const user = useState<GetUserResponse|null>('user', () => null)
const loading = useState<boolean>('userLoading', () => false)
const error = useState<string|null>('userError', () => null)

const fetchUser = async () => {
// Only fetch if we don't have user data
if (!user.value) {
loading.value = true
error.value = null
try {
user.value = await useProfileInformation()
} catch (err) {
error.value = 'Failed to fetch user'
console.error(err)
} finally {
loading.value = false
}
}
}

return {
user,
loading,
error,
fetchUser
}
}

async function useProfileInformation() {
return await $fetch<GetUserResponse>('http://localhost:3000/api/v1/user/')
}
34 changes: 34 additions & 0 deletions server/api/v1/user/index.get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {serverSupabaseServiceRole, serverSupabaseUser} from "#supabase/server";
import type {GetUserResponse} from "~/types/api/users";

export default defineEventHandler(async (event) => {

// Require user to be authenticated
const user = await serverSupabaseUser(event);
if (!user?.id) {
setResponseStatus(event, 401);
return {error: 'unauthenticated'};
}

// Send request
const client = serverSupabaseServiceRole(event);
const {data, error}:{ data: GetUserResponse|null, error: any} = await client.from('users').select('*').eq('id', user.id).maybeSingle();

Check failure on line 15 in server/api/v1/user/index.get.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type

Check failure on line 15 in server/api/v1/user/index.get.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type

if (!data) {
setResponseStatus(event, 404);
return {error: 'User not found'};
}

// Handle errors
if (error) {
setResponseStatus(event, 500);
return {error: error.message};
}

// Hide spotify id if not visible
if (!data.spotify_visibility) {
delete data.spotify_id;
}

return data;
})
4 changes: 1 addition & 3 deletions types/api/users.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type url from "node:url";

export interface GetUserResponse {
id: string,
avatar_url?: url.URL | null,
avatar_url?: string,
username: string,
spotify_id?: string,
spotify_visibility: boolean,
Expand Down

0 comments on commit e48df28

Please sign in to comment.