diff --git a/src/components/auth/StoreAuth.ts b/src/components/auth/StoreAuth.ts
index 2570132..21e43ad 100644
--- a/src/components/auth/StoreAuth.ts
+++ b/src/components/auth/StoreAuth.ts
@@ -25,6 +25,14 @@ interface AuthElements {
refreshResumes: HTMLButtonElement;
resumeSearch: HTMLInputElement;
searchResumes: HTMLButtonElement;
+ profileEditor: HTMLDialogElement;
+ editorName: HTMLInputElement;
+ editorEmail: HTMLInputElement;
+ editorMemberId: HTMLInputElement;
+ editorPoints: HTMLInputElement;
+ editorResume: HTMLInputElement;
+ editorCurrentResume: HTMLParagraphElement;
+ saveProfileButton: HTMLButtonElement;
}
export class StoreAuth {
@@ -128,6 +136,31 @@ export class StoreAuth {
"searchResumes",
) as HTMLButtonElement;
+ const profileEditor = document.getElementById(
+ "profileEditor",
+ ) as HTMLDialogElement;
+ const editorName = document.getElementById(
+ "editorName",
+ ) as HTMLInputElement;
+ const editorEmail = document.getElementById(
+ "editorEmail",
+ ) as HTMLInputElement;
+ const editorMemberId = document.getElementById(
+ "editorMemberId",
+ ) as HTMLInputElement;
+ const editorPoints = document.getElementById(
+ "editorPoints",
+ ) as HTMLInputElement;
+ const editorResume = document.getElementById(
+ "editorResume",
+ ) as HTMLInputElement;
+ const editorCurrentResume = document.getElementById(
+ "editorCurrentResume",
+ ) as HTMLParagraphElement;
+ const saveProfileButton = document.getElementById(
+ "saveProfileButton",
+ ) as HTMLButtonElement;
+
if (
!loginButton ||
!logoutButton ||
@@ -153,7 +186,15 @@ export class StoreAuth {
!resumeList ||
!refreshResumes ||
!resumeSearch ||
- !searchResumes
+ !searchResumes ||
+ !profileEditor ||
+ !editorName ||
+ !editorEmail ||
+ !editorMemberId ||
+ !editorPoints ||
+ !editorResume ||
+ !editorCurrentResume ||
+ !saveProfileButton
) {
throw new Error("Required DOM elements not found");
}
@@ -184,6 +225,14 @@ export class StoreAuth {
refreshResumes,
resumeSearch,
searchResumes,
+ profileEditor,
+ editorName,
+ editorEmail,
+ editorMemberId,
+ editorPoints,
+ editorResume,
+ editorCurrentResume,
+ saveProfileButton,
};
}
@@ -374,8 +423,13 @@ export class StoreAuth {
}
private getFileNameFromUrl(url: string): string {
- const parts = url.split("/");
- return parts[parts.length - 1];
+ try {
+ const urlObj = new URL(url);
+ const pathParts = urlObj.pathname.split("/");
+ return decodeURIComponent(pathParts[pathParts.length - 1]);
+ } catch (e) {
+ return url.split("/").pop() || "Unknown File";
+ }
}
private async handleMemberIdButton() {
@@ -436,6 +490,15 @@ export class StoreAuth {
throw new Error("User ID not found");
}
+ // Get current user data first
+ const currentUser = await this.pb.collection("users").getOne(user.id);
+
+ // Keep existing data
+ formData.append("name", currentUser.name || "");
+ formData.append("email", currentUser.email || "");
+ formData.append("member_id", currentUser.member_id || "");
+ formData.append("points", currentUser.points?.toString() || "0");
+
await this.pb.collection("users").update(user.id, formData);
uploadStatus.textContent = "Resume uploaded successfully!";
@@ -515,7 +578,7 @@ export class StoreAuth {
private async fetchUserResumes(searchQuery: string = "") {
try {
- let filter = 'resume != ""';
+ let filter = ""; // Remove the resume filter to show all users
if (searchQuery) {
const terms = searchQuery
.toLowerCase()
@@ -528,16 +591,20 @@ export class StoreAuth {
`(name ?~ "${term}" || email ?~ "${term}" || member_id ?~ "${term}")`,
)
.join(" && ");
- filter += ` && (${searchConditions})`;
+ filter = searchConditions; // Only apply search conditions
}
}
const records = await this.pb.collection("users").getList(1, 50, {
filter,
sort: "-updated",
- fields: "id,name,email,member_id,resume,updated,points",
+ fields:
+ "id,name,email,member_id,resume,points,collectionId,collectionName",
+ expand: "resume",
});
+ console.log("Fetched records:", records.items); // Debug log
+
const { resumeList } = this.elements;
const fragment = document.createDocumentFragment();
@@ -545,16 +612,19 @@ export class StoreAuth {
const row = document.createElement("tr");
row.innerHTML = `
- ${searchQuery ? "No users found matching your search." : "No resumes uploaded yet."}
+ ${searchQuery ? "No users found matching your search." : "No users found."}
`;
fragment.appendChild(row);
} else {
records.items.forEach((user) => {
const row = document.createElement("tr");
- const resumeUrl = user.resume
- ? this.pb.files.getURL(user, user.resume)
- : null;
+ const resumeUrl =
+ user.resume && user.resume !== ""
+ ? this.pb.files.getURL(user, user.resume.toString())
+ : null;
+
+ console.log("User resume:", user.resume, "Resume URL:", resumeUrl); // Debug log
row.innerHTML = `
@@ -563,40 +633,7 @@ export class StoreAuth {
${user.name || "N/A"}
${user.email || "N/A"}
ID: ${user.member_id || "N/A"}
-
-
-
Points:
-
-
${user.points || 0}
-
-
-
-
-
-
-
-
-
+ Points: ${user.points || 0}
${
resumeUrl
@@ -607,9 +644,12 @@ export class StoreAuth {
`
: '
No resume '
}
-
- ${new Date(user.updated).toLocaleDateString()}
-
+
+
+
+
+ Edit
+
@@ -618,37 +658,7 @@ export class StoreAuth {
${user.email || "N/A"}
${user.member_id || "N/A"}
-
-
-
${user.points || 0}
-
-
-
-
-
-
-
-
+ ${user.points || 0}
${
resumeUrl
@@ -660,7 +670,14 @@ export class StoreAuth {
: 'No resume '
}
- ${new Date(user.updated).toLocaleDateString()}
+
+
+
+
+
+ Edit Profile
+
+
`;
fragment.appendChild(row);
@@ -670,8 +687,16 @@ export class StoreAuth {
resumeList.innerHTML = "";
resumeList.appendChild(fragment);
- // Setup event listeners for the points editing functionality
- this.setupPointsEventListeners();
+ // Setup edit profile event listeners
+ const editButtons = resumeList.querySelectorAll(".edit-profile");
+ editButtons.forEach((button) => {
+ button.addEventListener("click", () => {
+ const userId = (button as HTMLButtonElement).dataset.userId;
+ if (userId) {
+ this.handleProfileEdit(userId);
+ }
+ });
+ });
} catch (err) {
console.error("Failed to fetch user resumes:", err);
const { resumeList } = this.elements;
@@ -685,131 +710,102 @@ export class StoreAuth {
}
}
- private async updateUserPoints(userId: string, points: number) {
+ private async handleProfileEdit(userId: string) {
try {
- await this.pb.collection("users").update(userId, {
- points: points,
- });
+ const user = await this.pb.collection("users").getOne(userId);
+ const {
+ profileEditor,
+ editorName,
+ editorEmail,
+ editorMemberId,
+ editorPoints,
+ editorCurrentResume,
+ saveProfileButton,
+ } = this.elements;
- // Update the display after successful update
- const displayElement = document.querySelector(
- `.points-display-${userId}`,
- ) as HTMLDivElement;
- const editElement = document.querySelector(
- `.points-edit-${userId}`,
- ) as HTMLDivElement;
- if (displayElement && editElement) {
- const pointsSpan = displayElement.querySelector("span");
- if (pointsSpan) {
- pointsSpan.textContent = points.toString();
- }
- displayElement.classList.remove("hidden");
- editElement.classList.add("hidden");
+ // Populate the form
+ editorName.value = user.name || "";
+ editorEmail.value = user.email || "";
+ editorMemberId.value = user.member_id || "";
+ editorPoints.value = user.points?.toString() || "0";
+
+ // Update resume display
+ if (user.resume) {
+ const resumeUrl = this.pb.files.getURL(user, user.resume.toString());
+ const fileName = this.getFileNameFromUrl(resumeUrl);
+ editorCurrentResume.textContent = `Current resume: ${fileName}`;
+ editorCurrentResume.classList.remove("opacity-70");
+ } else {
+ editorCurrentResume.textContent = "No resume uploaded";
+ editorCurrentResume.classList.add("opacity-70");
}
+
+ // Store the user ID for saving
+ saveProfileButton.dataset.userId = userId;
+
+ // Show the dialog
+ profileEditor.showModal();
} catch (err) {
- console.error("Failed to update points:", err);
+ console.error("Failed to load user for editing:", err);
}
}
- private setupPointsEventListeners() {
- // Use event delegation for all points-related actions
- const { resumeList } = this.elements;
+ private async handleProfileSave() {
+ const {
+ profileEditor,
+ editorName,
+ editorEmail,
+ editorMemberId,
+ editorPoints,
+ editorResume,
+ saveProfileButton,
+ } = this.elements;
+ const userId = saveProfileButton.dataset.userId;
- resumeList.addEventListener("click", async (e) => {
- console.log("Click event triggered");
- const target = e.target as HTMLElement;
- const button = target.closest("button");
- console.log("Button found:", button);
- if (!button) return;
+ if (!userId) {
+ console.error("No user ID found for saving");
+ return;
+ }
- const userId = button.dataset.userId;
- console.log("User ID:", userId);
- if (!userId) return;
+ try {
+ // First get the current user data to check existing resume
+ const currentUser = await this.pb.collection("users").getOne(userId);
- // Handle edit button click
- if (button.classList.contains("edit-points")) {
- console.log("Edit points button clicked");
- const row = button.closest("tr");
- if (!row) return;
+ const formData = new FormData();
+ formData.append("name", editorName.value);
+ formData.append("email", editorEmail.value);
+ formData.append("member_id", editorMemberId.value);
+ formData.append("points", editorPoints.value);
- const displayElement = row.querySelector(
- `.points-display-${userId}`,
- ) as HTMLDivElement;
- const editElement = row.querySelector(
- `.points-edit-${userId}`,
- ) as HTMLDivElement;
-
- console.log("Display element:", displayElement);
- console.log("Edit element:", editElement);
-
- if (displayElement && editElement) {
- const currentPoints =
- displayElement.querySelector("span")?.textContent;
- console.log("Current points:", currentPoints);
- const input = editElement.querySelector("input") as HTMLInputElement;
- console.log("Input element:", input);
- if (input && currentPoints) {
- input.value = currentPoints;
- }
-
- displayElement.classList.add("hidden");
- editElement.classList.remove("hidden");
- }
+ // Only append resume if a new file is selected
+ if (editorResume.files && editorResume.files.length > 0) {
+ formData.append("resume", editorResume.files[0]);
+ } else if (currentUser.resume) {
+ // If no new file but there's an existing resume, keep it
+ formData.append("resume", currentUser.resume);
}
- // Handle confirm button click
- if (button.classList.contains("confirm-points")) {
- const row = button.closest("tr");
- if (!row) return;
+ // Log the form data for debugging
+ console.log("Form data being sent:", {
+ name: editorName.value,
+ email: editorEmail.value,
+ member_id: editorMemberId.value,
+ points: editorPoints.value,
+ hasNewResume: editorResume.files && editorResume.files.length > 0,
+ hasExistingResume: !!currentUser.resume,
+ });
- const input = row.querySelector(
- `input[data-user-id="${userId}"]`,
- ) as HTMLInputElement;
- if (input) {
- const points = parseInt(input.value) || 0;
- await this.updateUserPoints(userId, points);
+ const updatedUser = await this.pb
+ .collection("users")
+ .update(userId, formData);
+ console.log("Update response:", updatedUser);
- const displayElement = row.querySelector(
- `.points-display-${userId}`,
- ) as HTMLDivElement;
- const editElement = row.querySelector(
- `.points-edit-${userId}`,
- ) as HTMLDivElement;
-
- if (displayElement && editElement) {
- displayElement.classList.remove("hidden");
- editElement.classList.add("hidden");
- }
- }
- }
-
- // Handle cancel button click
- if (button.classList.contains("cancel-points")) {
- const row = button.closest("tr");
- if (!row) return;
-
- const displayElement = row.querySelector(
- `.points-display-${userId}`,
- ) as HTMLDivElement;
- const editElement = row.querySelector(
- `.points-edit-${userId}`,
- ) as HTMLDivElement;
- const input = row.querySelector(
- `input[data-user-id="${userId}"]`,
- ) as HTMLInputElement;
- const currentPoints =
- displayElement?.querySelector("span")?.textContent;
-
- if (input && currentPoints) {
- input.value = currentPoints;
- }
-
- if (displayElement && editElement) {
- displayElement.classList.remove("hidden");
- editElement.classList.add("hidden");
- }
- }
- });
+ // Close the dialog and refresh the table
+ profileEditor.close();
+ this.fetchUserResumes();
+ } catch (err) {
+ console.error("Failed to save user profile:", err);
+ }
}
private init() {
@@ -883,5 +879,21 @@ export class StoreAuth {
console.log("Auth state changed. IsValid:", this.pb.authStore.isValid);
this.updateUI();
});
+
+ // Profile editor event listeners
+ const { profileEditor, saveProfileButton } = this.elements;
+
+ // Close dialog when clicking outside
+ profileEditor.addEventListener("click", (e) => {
+ if (e.target === profileEditor) {
+ profileEditor.close();
+ }
+ });
+
+ // Save profile button
+ saveProfileButton.addEventListener("click", (e) => {
+ e.preventDefault();
+ this.handleProfileSave();
+ });
}
}
diff --git a/src/components/auth/UserProfile.astro b/src/components/auth/UserProfile.astro
index b129a15..3394574 100644
--- a/src/components/auth/UserProfile.astro
+++ b/src/components/auth/UserProfile.astro
@@ -171,6 +171,76 @@
+
+
+
+
+
+
diff --git a/src/pages/online-store.astro b/src/pages/online-store.astro
index 58e46f0..68dc235 100644
--- a/src/pages/online-store.astro
+++ b/src/pages/online-store.astro
@@ -103,7 +103,7 @@ const title = "IEEE Store";
Member ID
Points
Resume
- Last Updated
+ Actions