updateweb
This commit is contained in:
266
website/admin/js/team-members.js
Normal file
266
website/admin/js/team-members.js
Normal file
@@ -0,0 +1,266 @@
|
||||
let teamMemberModal, notificationModal, confirmationModal;
|
||||
let currentMemberId = null;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
teamMemberModal = new bootstrap.Modal(
|
||||
document.getElementById("teamMemberModal")
|
||||
);
|
||||
notificationModal = new bootstrap.Modal(
|
||||
document.getElementById("notificationModal")
|
||||
);
|
||||
confirmationModal = new bootstrap.Modal(
|
||||
document.getElementById("confirmationModal")
|
||||
);
|
||||
|
||||
checkAuth().then((authenticated) => {
|
||||
if (authenticated) {
|
||||
loadTeamMembers();
|
||||
}
|
||||
});
|
||||
|
||||
// Image preview on URL change
|
||||
document.getElementById("memberImage").addEventListener("input", function () {
|
||||
updateImagePreview(this.value);
|
||||
});
|
||||
});
|
||||
|
||||
// Load all team members
|
||||
async function loadTeamMembers() {
|
||||
try {
|
||||
const response = await fetch("/api/admin/team-members");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.teamMembers) {
|
||||
displayTeamMembers(data.teamMembers);
|
||||
} else {
|
||||
showNotification("Failed to load team members", "error");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading team members:", error);
|
||||
showNotification("Error loading team members", "error");
|
||||
}
|
||||
}
|
||||
|
||||
// Display team members in grid
|
||||
function displayTeamMembers(members) {
|
||||
const container = document.getElementById("teamMembersContainer");
|
||||
|
||||
if (members.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="col-12 text-center py-5">
|
||||
<i class="bi bi-people" style="font-size: 4rem; color: #cbd5e0;"></i>
|
||||
<p class="mt-3 text-muted">No team members yet. Add your first team member!</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = members
|
||||
.map(
|
||||
(member) => `
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="team-preview-card">
|
||||
<div class="team-preview-image">
|
||||
${
|
||||
member.image_url
|
||||
? `<img src="${member.image_url}" alt="${member.name}" />`
|
||||
: `<i class="bi bi-person-circle"></i>`
|
||||
}
|
||||
</div>
|
||||
<div class="team-preview-name">${escapeHtml(member.name)}</div>
|
||||
<div class="team-preview-position">${escapeHtml(member.position)}</div>
|
||||
<div class="team-preview-bio">${
|
||||
member.bio ? escapeHtml(member.bio) : ""
|
||||
}</div>
|
||||
<div class="mt-3 d-flex justify-content-center gap-2">
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="editTeamMember('${
|
||||
member.id
|
||||
}')">
|
||||
<i class="bi bi-pencil"></i> Edit
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="confirmDelete('${
|
||||
member.id
|
||||
}', '${escapeHtml(member.name)}')">
|
||||
<i class="bi bi-trash"></i> Delete
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<small class="text-muted">Order: ${member.display_order}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
// Show add modal
|
||||
function showAddModal() {
|
||||
currentMemberId = null;
|
||||
document.getElementById("modalTitle").textContent = "Add Team Member";
|
||||
document.getElementById("teamMemberForm").reset();
|
||||
document.getElementById("memberId").value = "";
|
||||
document.getElementById("imagePreview").innerHTML = "";
|
||||
teamMemberModal.show();
|
||||
}
|
||||
|
||||
// Edit team member
|
||||
async function editTeamMember(id) {
|
||||
try {
|
||||
const response = await fetch(`/api/admin/team-members/${id}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.teamMember) {
|
||||
currentMemberId = id;
|
||||
const member = data.teamMember;
|
||||
|
||||
document.getElementById("modalTitle").textContent = "Edit Team Member";
|
||||
document.getElementById("memberId").value = member.id;
|
||||
document.getElementById("memberName").value = member.name;
|
||||
document.getElementById("memberPosition").value = member.position;
|
||||
document.getElementById("memberBio").value = member.bio || "";
|
||||
document.getElementById("memberImage").value = member.image_url || "";
|
||||
document.getElementById("displayOrder").value = member.display_order || 0;
|
||||
|
||||
updateImagePreview(member.image_url);
|
||||
teamMemberModal.show();
|
||||
} else {
|
||||
showNotification("Failed to load team member details", "error");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading team member:", error);
|
||||
showNotification("Error loading team member", "error");
|
||||
}
|
||||
}
|
||||
|
||||
// Save team member (create or update)
|
||||
async function saveTeamMember() {
|
||||
const id = document.getElementById("memberId").value;
|
||||
const name = document.getElementById("memberName").value.trim();
|
||||
const position = document.getElementById("memberPosition").value.trim();
|
||||
const bio = document.getElementById("memberBio").value.trim();
|
||||
const image_url = document.getElementById("memberImage").value.trim();
|
||||
const display_order =
|
||||
parseInt(document.getElementById("displayOrder").value) || 0;
|
||||
|
||||
if (!name || !position) {
|
||||
showNotification("Name and position are required", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
name,
|
||||
position,
|
||||
bio,
|
||||
image_url,
|
||||
display_order,
|
||||
};
|
||||
|
||||
try {
|
||||
const url = id
|
||||
? `/api/admin/team-members/${id}`
|
||||
: "/api/admin/team-members";
|
||||
const method = id ? "PUT" : "POST";
|
||||
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
showNotification(
|
||||
data.message || "Team member saved successfully",
|
||||
"success"
|
||||
);
|
||||
teamMemberModal.hide();
|
||||
loadTeamMembers();
|
||||
} else {
|
||||
showNotification(data.message || "Failed to save team member", "error");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error saving team member:", error);
|
||||
showNotification("Error saving team member", "error");
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm delete
|
||||
function confirmDelete(id, name) {
|
||||
currentMemberId = id;
|
||||
document.getElementById(
|
||||
"confirmationMessage"
|
||||
).textContent = `Are you sure you want to delete "${name}"? This action cannot be undone.`;
|
||||
|
||||
const confirmBtn = document.getElementById("confirmButton");
|
||||
confirmBtn.onclick = () => deleteTeamMember(id);
|
||||
|
||||
confirmationModal.show();
|
||||
}
|
||||
|
||||
// Delete team member
|
||||
async function deleteTeamMember(id) {
|
||||
try {
|
||||
const response = await fetch(`/api/admin/team-members/${id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
showNotification("Team member deleted successfully", "success");
|
||||
confirmationModal.hide();
|
||||
loadTeamMembers();
|
||||
} else {
|
||||
showNotification("Failed to delete team member", "error");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error deleting team member:", error);
|
||||
showNotification("Error deleting team member", "error");
|
||||
}
|
||||
}
|
||||
|
||||
// Update image preview
|
||||
function updateImagePreview(url) {
|
||||
const preview = document.getElementById("imagePreview");
|
||||
if (url) {
|
||||
preview.innerHTML = `
|
||||
<img src="${url}" alt="Preview" style="max-width: 150px; max-height: 150px; border-radius: 50%; border: 3px solid #667eea;" />
|
||||
`;
|
||||
} else {
|
||||
preview.innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Open media library (placeholder for future integration)
|
||||
function openMediaLibrary() {
|
||||
// For now, redirect to media library in a new window
|
||||
window.open("/admin/media-library.html", "_blank");
|
||||
showNotification(
|
||||
"Select an image from the media library and copy its URL back here",
|
||||
"success"
|
||||
);
|
||||
}
|
||||
|
||||
// Show notification
|
||||
function showNotification(message, type = "success") {
|
||||
const modal = document.getElementById("notificationModal");
|
||||
const header = modal.querySelector(".modal-header");
|
||||
const messageEl = document.getElementById("notificationMessage");
|
||||
const title = document.getElementById("notificationTitle");
|
||||
|
||||
header.className = "modal-header " + type;
|
||||
title.textContent = type === "success" ? "Success" : "Error";
|
||||
messageEl.textContent = message;
|
||||
|
||||
notificationModal.show();
|
||||
}
|
||||
|
||||
// Escape HTML
|
||||
function escapeHtml(text) {
|
||||
if (!text) return "";
|
||||
const div = document.createElement("div");
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
Reference in New Issue
Block a user