Merge pull request 'feat: fixed admin page, settings on user' (#12) from feature/profile-edit into develop
Reviewed-on: https://gitea.fernandovideira.com/SyntaxSquad/DAEProject_Frontend/pulls/12 Reviewed-by: FernandoJVideira <[email protected]> Reviewed-by: Edd <[email protected]>
This commit was merged in pull request #12.
This commit is contained in:
@@ -499,28 +499,7 @@ const authStore = useAuthStore();
|
|||||||
const { token } = storeToRefs(authStore);
|
const { token } = storeToRefs(authStore);
|
||||||
|
|
||||||
// State
|
// State
|
||||||
const users = ref<any[]>([
|
const users = ref<any[]>([]);
|
||||||
{ id: 1, name: 'Dr. Sarah Mitchell', email: '[email protected]', role: 'ADMIN', is_active: true },
|
|
||||||
{ id: 2, name: 'Prof. James Anderson', email: '[email protected]', role: 'TEACHER', is_active: true },
|
|
||||||
{ id: 3, name: 'Dr. Emily Chen', email: '[email protected]', role: 'RESEARCHER', is_active: true },
|
|
||||||
{ id: 4, name: 'Michael Roberts', email: '[email protected]', role: 'STUDENT', is_active: true },
|
|
||||||
{ id: 5, name: 'Dr. David Kim', email: '[email protected]', role: 'COLLABORATOR', is_active: true },
|
|
||||||
{ id: 6, name: 'Prof. Maria Garcia', email: '[email protected]', role: 'TEACHER', is_active: true },
|
|
||||||
{ id: 7, name: 'Jessica Thompson', email: '[email protected]', role: 'STUDENT', is_active: true },
|
|
||||||
{ id: 8, name: 'Dr. Robert Wilson', email: '[email protected]', role: 'RESEARCHER', is_active: true },
|
|
||||||
{ id: 9, name: 'Amanda Foster', email: '[email protected]', role: 'STUDENT', is_active: false },
|
|
||||||
{ id: 10, name: 'Prof. Thomas Lee', email: '[email protected]', role: 'ADMIN', is_active: true },
|
|
||||||
{ id: 11, name: 'Dr. Lisa Martinez', email: '[email protected]', role: 'RESEARCHER', is_active: true },
|
|
||||||
{ id: 12, name: 'Daniel Brown', email: '[email protected]', role: 'STUDENT', is_active: true },
|
|
||||||
{ id: 13, name: 'Prof. Jennifer Davis', email: '[email protected]', role: 'TEACHER', is_active: true },
|
|
||||||
{ id: 14, name: 'Christopher Taylor', email: '[email protected]', role: 'STUDENT', is_active: false },
|
|
||||||
{ id: 15, name: 'Dr. Patricia Johnson', email: '[email protected]', role: 'COLLABORATOR', is_active: true },
|
|
||||||
{ id: 16, name: 'Matthew White', email: '[email protected]', role: 'STUDENT', is_active: true },
|
|
||||||
{ id: 17, name: 'Prof. Elizabeth Moore', email: '[email protected]', role: 'TEACHER', is_active: true },
|
|
||||||
{ id: 18, name: 'Dr. William Harris', email: '[email protected]', role: 'RESEARCHER', is_active: true },
|
|
||||||
{ id: 19, name: 'Sophie Anderson', email: '[email protected]', role: 'STUDENT', is_active: true },
|
|
||||||
{ id: 20, name: 'Dr. Richard Clark', email: '[email protected]', role: 'ADMIN', is_active: true }
|
|
||||||
]);
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const showModal = ref(false);
|
const showModal = ref(false);
|
||||||
const showDetailsModal = ref(false);
|
const showDetailsModal = ref(false);
|
||||||
|
|||||||
+126
-16
@@ -427,17 +427,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="userProfile.publications.length === 0" class="...">
|
<div v-if="userProfile.publications.length === 0 && !loading"
|
||||||
<div
|
|
||||||
class="relative overflow-hidden rounded-2xl border-2 border-dashed border-slate-300 dark:border-slate-700 bg-slate-50 dark:bg-slate-900/50 p-12 text-center hover:border-blue-400 dark:hover:border-blue-500 transition-all duration-300 group">
|
class="relative overflow-hidden rounded-2xl border-2 border-dashed border-slate-300 dark:border-slate-700 bg-slate-50 dark:bg-slate-900/50 p-12 text-center hover:border-blue-400 dark:hover:border-blue-500 transition-all duration-300 group">
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-48 h-48 bg-blue-500/10 dark:bg-blue-400/10 rounded-full blur-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none" />
|
||||||
|
|
||||||
<div class="relative z-10 flex flex-col items-center">
|
<div class="relative z-10 flex flex-col items-center">
|
||||||
<h3 class="text-lg font-bold text-slate-900 dark:text-white mb-1">No
|
<div
|
||||||
publications yet</h3>
|
class="mb-4 p-4 bg-white dark:bg-slate-800 rounded-full shadow-sm ring-1 ring-slate-100 dark:ring-slate-700 group-hover:scale-110 group-hover:ring-blue-200 dark:group-hover:ring-blue-800 transition-all duration-300">
|
||||||
<button @click="goToCreatePost()"
|
<svg class="w-8 h-8 text-blue-500 dark:text-blue-400" fill="none"
|
||||||
class="mt-4 inline-flex items-center gap-2 px-6 py-2.5 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-xl shadow-lg transition-all cursor-pointer">
|
viewBox="0 0 24 24" stroke="currentColor">
|
||||||
Submit your first paper
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
||||||
</button>
|
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3 class="text-lg font-bold text-slate-900 dark:text-white mb-1">
|
||||||
|
No publications yet
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="inline-flex items-center gap-2 px-6 py-2.5 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-xl shadow-lg shadow-blue-500/20 hover:shadow-blue-500/30 transform active:scale-95 transition-all duration-200 cursor-pointer"
|
||||||
|
@click="isModalOpen = true">
|
||||||
|
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M12 4v16m8-8H4" />
|
||||||
|
</svg>
|
||||||
|
Submit your first post
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -585,14 +603,68 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="activeTab === 'settings'" key="settings"
|
<div v-else-if="activeTab === 'settings'" key="settings"
|
||||||
class="bg-white dark:bg-slate-900 p-6 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-800 transition-colors">
|
class="bg-white dark:bg-slate-900 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-800 transition-colors">
|
||||||
<h2
|
<!-- Header -->
|
||||||
class="text-xs font-bold text-slate-400 dark:text-slate-500 uppercase tracking-wider mb-3">
|
<div class="px-6 py-5 border-b border-slate-200 dark:border-slate-800">
|
||||||
Settings</h2>
|
<h2 class="text-lg font-semibold text-slate-900 dark:text-white">
|
||||||
<p class="text-sm text-slate-600 dark:text-slate-400">
|
Edit Profile
|
||||||
Nothing here but chickens! Settings coming soon.
|
</h2>
|
||||||
|
<p class="text-sm text-slate-500 dark:text-slate-400 mt-1">
|
||||||
|
Update your personal information and account details.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="p-6 space-y-6">
|
||||||
|
<div>
|
||||||
|
<label for="name"
|
||||||
|
class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
|
<input id="name" type="text" v-model="newUsername"
|
||||||
|
placeholder="Your first name and last name" class="w-full px-4 py-2.5 bg-white dark:bg-slate-800
|
||||||
|
border border-slate-300 dark:border-slate-700
|
||||||
|
rounded-xl text-slate-900 dark:text-white
|
||||||
|
placeholder-slate-400
|
||||||
|
focus:ring-2 focus:ring-blue-500 focus:border-blue-500
|
||||||
|
outline-none transition-all" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="email"
|
||||||
|
class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
|
||||||
|
Email address
|
||||||
|
</label>
|
||||||
|
<input id="email" type="email" v-model="newEmail" placeholder="[email protected]"
|
||||||
|
class="w-full px-4 py-2.5 bg-white dark:bg-slate-800
|
||||||
|
border border-slate-300 dark:border-slate-700
|
||||||
|
rounded-xl text-slate-900 dark:text-white
|
||||||
|
placeholder-slate-400
|
||||||
|
focus:ring-2 focus:ring-blue-500 focus:border-blue-500
|
||||||
|
outline-none transition-all" />
|
||||||
|
<p class="mt-1 text-xs text-slate-500 dark:text-slate-400">
|
||||||
|
Dont worry, Your email is going to be sold to russian hackers.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a @click="openResetPassword" class="text-sm text-red dark:text-red-600 hover:underline">
|
||||||
|
Reset Password
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer / Actions -->
|
||||||
|
<div class="px-6 py-4 bg-slate-50 dark:bg-slate-800/50
|
||||||
|
border-t border-slate-200 dark:border-slate-800
|
||||||
|
flex justify-end">
|
||||||
|
<button @click="updateProfile" class="inline-flex items-center gap-2
|
||||||
|
bg-blue-600 hover:bg-blue-700
|
||||||
|
text-white font-semibold
|
||||||
|
px-6 py-2.5 rounded-xl
|
||||||
|
shadow-sm transition-all
|
||||||
|
active:scale-95">
|
||||||
|
Save changes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -625,6 +697,9 @@ const page = ref(1);
|
|||||||
const selectedPost = ref(null);
|
const selectedPost = ref(null);
|
||||||
const newCommentContent = ref('');
|
const newCommentContent = ref('');
|
||||||
|
|
||||||
|
const newUsername = ref('');
|
||||||
|
const newEmail = ref('');
|
||||||
|
|
||||||
interface Tag {
|
interface Tag {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -668,8 +743,6 @@ const userProfile = ref({
|
|||||||
role: '',
|
role: '',
|
||||||
is_active: false,
|
is_active: false,
|
||||||
avatarUrl: '',
|
avatarUrl: '',
|
||||||
biography: 'No biography provided.',
|
|
||||||
joinDate: new Date().toISOString(),
|
|
||||||
publications: [] as any[]
|
publications: [] as any[]
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -870,6 +943,39 @@ const confirmHide = async (post) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateProfile = async () => {
|
||||||
|
if (!token.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const name = newUsername.value.trim();
|
||||||
|
const email = newEmail.value.trim();
|
||||||
|
|
||||||
|
if (name.length === 0 || email.length === 0) {
|
||||||
|
alert("Name and email cannot be empty.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await $fetch(`${api}/users/me`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { Authorization: `Bearer ${token.value}` },
|
||||||
|
body: {
|
||||||
|
name: name,
|
||||||
|
email: email
|
||||||
|
}
|
||||||
|
});
|
||||||
|
alert("Profile updated successfully. Please log in again.");
|
||||||
|
authStore.logout();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Profile update failed", error);
|
||||||
|
alert("Failed to update profile.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchProfileData();
|
||||||
|
};
|
||||||
|
|
||||||
// --- Redirects ---
|
// --- Redirects ---
|
||||||
const goToCreatePost = () => {
|
const goToCreatePost = () => {
|
||||||
console.log("Navigating to create post modal...");
|
console.log("Navigating to create post modal...");
|
||||||
@@ -879,6 +985,10 @@ const goToCreatePost = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openResetPassword = () => {
|
||||||
|
router.push({ path: '/profile/update-password' });
|
||||||
|
};
|
||||||
|
|
||||||
// --- Lifecycle ---
|
// --- Lifecycle ---
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchProfileData();
|
fetchProfileData();
|
||||||
|
|||||||
Reference in New Issue
Block a user