Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
104 lines
3.2 KiB
Vue
104 lines
3.2 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import { Icon } from '@iconify/vue';
|
|
|
|
const props = defineProps<{
|
|
user: {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
};
|
|
}>();
|
|
|
|
const name = ref(props.user.name);
|
|
const loading = ref(false);
|
|
const message = ref<{ type: 'success' | 'error'; text: string } | null>(null);
|
|
|
|
async function updateProfile() {
|
|
loading.value = true;
|
|
message.value = null;
|
|
|
|
try {
|
|
const response = await fetch('/api/user/update-profile', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ name: name.value }),
|
|
});
|
|
|
|
if (response.ok) {
|
|
message.value = { type: 'success', text: 'Profile updated successfully!' };
|
|
// Hide success message after 3 seconds
|
|
setTimeout(() => {
|
|
message.value = null;
|
|
}, 3000);
|
|
} else {
|
|
const data = await response.json().catch(() => ({}));
|
|
message.value = { type: 'error', text: data.error || 'Failed to update profile' };
|
|
}
|
|
} catch (error) {
|
|
message.value = { type: 'error', text: 'An error occurred' };
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<!-- Success/Error Message Display -->
|
|
<div v-if="message" :class="['alert mb-6', message.type === 'success' ? 'alert-success' : 'alert-error']">
|
|
<Icon :icon="message.type === 'success' ? 'heroicons:check-circle' : 'heroicons:exclamation-circle'" class="w-6 h-6 shrink-0" />
|
|
<span>{{ message.text }}</span>
|
|
</div>
|
|
|
|
<div class="card bg-base-100 shadow-xl border border-base-200 mb-6">
|
|
<div class="card-body p-4 sm:p-6">
|
|
<h2 class="card-title mb-6 text-lg sm:text-xl">
|
|
<Icon icon="heroicons:user-circle" class="w-5 h-5 sm:w-6 sm:h-6" />
|
|
Profile Information
|
|
</h2>
|
|
|
|
<form @submit.prevent="updateProfile" class="space-y-5">
|
|
<div class="form-control">
|
|
<label class="label pb-2">
|
|
<span class="label-text font-medium text-sm sm:text-base">Full Name</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
v-model="name"
|
|
placeholder="Your full name"
|
|
class="input input-bordered w-full"
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div class="form-control">
|
|
<label class="label pb-2">
|
|
<span class="label-text font-medium text-sm sm:text-base">Email</span>
|
|
</label>
|
|
<input
|
|
type="email"
|
|
:value="props.user.email"
|
|
class="input input-bordered w-full"
|
|
disabled
|
|
/>
|
|
<div class="label pt-2">
|
|
<span class="label-text-alt text-base-content/60 text-xs sm:text-sm">Email cannot be changed</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex justify-end pt-4">
|
|
<button type="submit" class="btn btn-primary w-full sm:w-auto" :disabled="loading">
|
|
<span v-if="loading" class="loading loading-spinner loading-sm"></span>
|
|
<Icon v-else icon="heroicons:check" class="w-5 h-5" />
|
|
Save Changes
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|