Files
SkyArtShop/website/admin/js/team-members.js
Local Server 017c6376fc updateweb
2025-12-24 00:13:23 -06:00

267 lines
7.9 KiB
JavaScript

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;
}