Skip to content

Commit

Permalink
feat!: add profile editing functionality with visibility toggle
Browse files Browse the repository at this point in the history
Co-Authored-By: Chris Saganic <[email protected]>
Co-Authored-By: Jorge A. <[email protected]>
  • Loading branch information
3 people committed Feb 6, 2025
1 parent fa612fc commit a5b303e
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
4 changes: 2 additions & 2 deletions app/components/Dropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const isDarkMode = computed({
</UPopover>
<UModal
v-model="openEditProfile"
:ui="{ container: 'items-center', background: '', shadow: '', overlay: { base: 'backdrop-blur-2xl', background: 'bg-white/5 dark:bg-black/60' } }">
<div class="flex flex-col gap-4"></div>
:ui="{ container: 'items-center', width: 'w-96', background: '', shadow: '', overlay: { base: 'backdrop-blur-2xl', background: 'bg-white/5 dark:bg-black/60' } }">
<ProfileForm :user="user" />
</UModal>
</template>

Expand Down
58 changes: 58 additions & 0 deletions app/components/ProfileForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script setup lang="ts">
import { z } from 'zod';
const props = defineProps<{ user: User }>();
const emit = defineEmits<{ (e: 'profileUpdated'): void }>();
const schema = z.object({ userView: z.boolean() });
type Schema = z.infer<typeof schema>;
const formState = reactive<Schema>({
userView: !!props.user.userView,
});
const queryCache = useQueryCache();
const { mutate: editProfile } = useMutation({
mutation: (data: Schema) =>
$fetch('/api/users', {
method: 'PATCH',
body: data,
}) as Promise<User>,
async onSuccess() {
await queryCache.invalidateQueries({ key: ['user'] });
emit('profileUpdated');
},
onSettled() {
formState.userView = !!props.user.userView;
},
});
const updateProfile = () => {
editProfile({ userView: formState.userView });
};
const accountVisibilityMessage = computed(() => {
return formState.userView
? 'Your profile is <strong>public</strong>. Habits set to public can be viewed by anyone, even without logging in.'
: 'Your profile is <strong>private</strong>. Only you can view your habits.';
});
</script>

<template>
<div class="p-8">
<UForm :schema="schema" :state="formState" class="flex flex-col gap-4">
<ContentBox class="flex items-center justify-between gap-14 bg-white/10 p-4 backdrop-blur-2xl dark:bg-neutral-200/5">
<div class="flex flex-col gap-1">
<div class="text-sm font-semibold text-white">Public Account</div>
<div class="text-xs text-white/60" v-html="accountVisibilityMessage"></div>
</div>
<UFormGroup name="userView">
<UToggle v-model="formState.userView" @update:model-value="updateProfile" />
</UFormGroup>
</ContentBox>
</UForm>
</div>
</template>
16 changes: 16 additions & 0 deletions server/api/users/index.patch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { eq } from 'drizzle-orm';
import { useValidatedBody, z } from 'h3-zod';

export default eventHandler(async event => {
const { userView } = await useValidatedBody(event, {
userView: z.boolean().optional(),
});

const { user: requestUser } = await requireUserSession(event);

const updatedFields: Partial<{ userView: boolean }> = { userView };

const user = await useDB().update(tables.users).set(updatedFields).where(eq(tables.users.id, requestUser.id)).returning().get();

return user;
});

0 comments on commit a5b303e

Please sign in to comment.