Files
cms.uldp.edu.vn/views/admin/visa/index.ejs
2026-02-05 12:49:59 +07:00

1003 lines
53 KiB
Plaintext

<div class="container">
<div class="d-flex justify-content-between align-items-center mt-4 mb-4">
<div>
<h1 class="h3 mb-0" style="color: var(--primary-dark)">
Visa Management
</h1>
<p class="text-muted mb-0">Manage visa information for different countries</p>
</div>
<div>
<button type="button" class="btn btn-primary" id="btnAddCountry">
<i class="fas fa-plus-circle me-2"></i>Add Country
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<!-- Table View -->
<div class="card shadow-sm border-0 mb-4" id="tableContainer">
<div class="card-header bg-white border-bottom">
<h6 class="mb-0">Countries List</h6>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th style="width: 8%" class="text-center">ID</th>
<th style="width: 10%" class="text-center">Flag</th>
<th style="width: 22%">Country Name</th>
<th style="width: 40%">Services</th>
<th style="width: 20%" class="text-center">Actions</th>
</tr>
</thead>
<tbody>
<% if (data && data.hero && data.hero.summaryList) { %>
<% data.hero.summaryList.forEach(function(country) { %>
<tr>
<td class="text-center align-middle">
<span class="badge bg-secondary">#<%= String(country.id).padStart(3, "0") %></span>
</td>
<td class="text-center align-middle">
<img src="<%= country.icon %>" alt="<%= country.name %>" style="width: 40px; height: 40px; object-fit: contain;">
</td>
<td class="align-middle">
<strong><%= country.name %></strong>
<div class="small text-muted">Slug: <%= country.slug %></div>
</td>
<td class="align-middle">
<% country.services.forEach(function(service) { %>
<span class="badge bg-light text-dark me-1"><%= service %></span>
<% }); %>
</td>
<td class="text-center align-middle">
<!-- <button class="btn btn-sm btn-outline-info" onclick="viewCountry('<%= country.id %>')" title="View">
<i class="fas fa-eye"></i>
</button> -->
<button class="btn btn-sm btn-outline-warning" onclick="editCountry('<%= country.id %>')" title="Edit">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-sm btn-outline-danger" onclick="deleteCountry('<%= country.id %>')" title="Delete">
<i class="fas fa-trash-alt"></i>
</button>
</td>
</tr>
<% }); %>
<% } %>
</tbody>
</table>
</div>
</div>
</div>
<!-- Form View -->
<div class="card shadow-sm border-0 mb-4" id="formContainer" style="display: none;">
<div class="card-header bg-white border-bottom">
<ul class="nav nav-tabs card-header-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="tab" href="#tab-summary" role="tab">
<i class="fas fa-map-marker-alt me-2"></i>Summary
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#tab-detail" role="tab">
<i class="fas fa-file-alt me-2"></i>Details
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#tab-contact" role="tab">
<i class="fas fa-phone-alt me-2"></i>Contact
</a>
</li>
</ul>
</div>
<div class="card-body">
<form id="formCountry">
<input type="hidden" name="country_id" id="country_id" />
<div class="tab-content">
<!-- Tab 1: Summary -->
<div class="tab-pane fade show active" id="tab-summary" role="tabpanel">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label fw-medium">Country Name</label>
<input type="text" name="name" class="form-control" placeholder="e.g. France" required />
</div>
<div class="col-md-6">
<label class="form-label fw-medium">Country Icon (Flag)</label>
<div class="input-group mb-2">
<input type="text" name="icon" id="icon_input" class="form-control" placeholder="/uploads/visa/flag.png" required />
<button type="button" class="btn btn-outline-secondary" onclick="document.getElementById('fileFlagInput').click()">
<i class="fas fa-upload"></i>
</button>
</div>
<input type="file" id="fileFlagInput" style="display:none" accept="image/*" />
<div style="margin-top: 10px;">
<img id="preview_icon" src="" alt="Icon Preview" style="max-width: 100px; max-height: 100px; object-fit: contain; display: none; border-radius: 4px; border: 1px solid #ddd;">
</div>
</div>
<div class="col-md-12">
<label class="form-label fw-medium">Visa Services (4 services)</label>
</div>
<% for(let i=1; i <=4; i++) { %>
<div class="col-md-6">
<input type="text" name="services[]" class="form-control" placeholder="Service <%= i %>" required/>
</div>
<% } %>
</div>
</div>
<!-- Tab 2: Details -->
<div class="tab-pane fade" id="tab-detail" role="tabpanel">
<div class="row g-4">
<!-- Basic Information -->
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-info-circle me-2"></i>Basic Information</h6>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-12">
<label class="form-label fw-medium">Banner Title</label>
<input type="text" name="detail_title" class="form-control" placeholder="COUNTRY USA" required/>
</div>
<div class="col-md-12">
<label class="form-label fw-medium">Main Image</label>
<div class="input-group mb-2">
<input type="text" id="mainImage_detail" name="mainImage" class="form-control" placeholder="/uploads/visa/details-1.jpg" required />
<button type="button" class="btn btn-outline-secondary" onclick="document.getElementById('fileDetailMainInput').click()">
<i class="fas fa-upload"></i>
</button>
</div>
<input type="file" id="fileDetailMainInput" style="display:none" accept="image/*"/>
<div style="margin-top: 10px;">
<img id="preview_main_detail" src="" alt="Main Image Preview" style="max-width: 200px; max-height: 150px; object-fit: cover; display: none; border-radius: 4px; border: 1px solid #ddd;">
</div>
</div>
<div class="col-md-6">
<label class="form-label fw-medium">Main Description</label>
<textarea name="description" class="form-control" rows="5" required></textarea>
</div>
<div class="col-md-6">
<label class="form-label fw-medium">Additional Info</label>
<textarea name="additionalInfo" class="form-control" rows="5" required></textarea>
</div>
<div class="col-md-12">
<label class="form-label fw-medium">Tagline</label>
<input type="text" name="tagline" class="form-control" required />
</div>
</div>
</div>
</div>
</div>
<!-- Visa Types -->
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-file-contract me-2"></i>Visa Types</h6>
</div>
<div class="card-body">
<div class="row g-3">
<% for(let i=1; i<=4; i++) { %>
<div class="col-md-6">
<label class="form-label fw-medium">Type <%= i %> Title</label>
<input type="text" name="visa_title_<%= i %>" class="form-control" placeholder="e.g. Tourist Visa" required />
<label class="form-label fw-medium mt-2">Description</label>
<textarea name="visa_desc_<%= i %>" class="form-control" rows="3" required></textarea>
</div>
<% } %>
</div>
</div>
</div>
</div>
<!-- Visa Process -->
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-list-check me-2"></i>Visa Process</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label fw-medium">Process Title</label>
<input type="text" name="process_title" class="form-control" placeholder="e.g. USA Visa Process" required />
</div>
<div class="row g-3">
<% for(let i=1; i<=5; i++) { %>
<div class="col-md-12">
<div class="card bg-light">
<div class="card-body">
<div class="d-flex align-items-center gap-2 mb-2">
<span class="badge bg-secondary"><%= i %></span>
<input type="text" name="step_title[]" class="form-control form-control-sm" placeholder="Step <%= i %> Title" required />
</div>
<textarea name="step_desc[]" class="form-control form-control-sm" rows="2" placeholder="Step <%= i %> Description" required></textarea>
</div>
</div>
</div>
<% } %>
</div>
</div>
</div>
</div>
<!-- Gallery -->
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-images me-2"></i>Gallery</h6>
</div>
<div class="card-body">
<div class="row g-3">
<% for(let i=1; i<=2; i++) { %>
<div class="col-md-12">
<label class="form-label fw-medium">Gallery Image <%= i %></label>
<div class="input-group mb-2">
<input type="text" class="form-control" id="bannerImageGallery<%= i %>" name="bannerImageGallery" placeholder="https://example.com/image.jpg" required />
<button type="button" class="btn btn-outline-secondary" onclick="document.getElementById('fileGalleryInput<%= i %>').click()">
<i class="fas fa-upload"></i>
</button>
</div>
<input type="file" id="fileGalleryInput<%= i %>" style="display:none" accept="image/*">
<div style="margin-top: 10px;">
<img id="preview_bannerImageGallery<%= i %>" src="" alt="Gallery Image Preview" style="max-width: 200px; max-height: 150px; object-fit: cover; display: none; border-radius: 4px; border: 1px solid #ddd;">
</div>
</div>
<% } %>
</div>
</div>
</div>
</div>
<!-- Visa Categories -->
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-layer-group me-2"></i>Visa Categories</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label fw-medium">Categories Title</label>
<input type="text" name="visa_categories_title" class="form-control" placeholder="e.g. Types of USA Visas" required />
</div>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label fw-medium small">Group 1 (3 Items)</label>
<input type="text" name="category_group1[]" class="form-control form-control-sm mb-2" placeholder="Item 1" required />
<input type="text" name="category_group1[]" class="form-control form-control-sm mb-2" placeholder="Item 2" required />
<input type="text" name="category_group1[]" class="form-control form-control-sm" placeholder="Item 3" required />
</div>
<div class="col-md-6">
<label class="form-label fw-medium small">Group 2 (2 Items)</label>
<input type="text" name="category_group2[]" class="form-control form-control-sm mb-2" placeholder="Item 1" required />
<input type="text" name="category_group2[]" class="form-control form-control-sm" placeholder="Item 2" required />
</div>
</div>
</div>
</div>
</div>
<!-- Service Options -->
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-briefcase me-2"></i>Service Options</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label fw-medium">Service Title</label>
<input type="text" name="service_main_title" class="form-control" placeholder="e.g. Our Visa Service Options" required />
</div>
<div class="row g-3">
<% for(let i=1; i<=5; i++) { %>
<div class="col-md-12">
<div class="card bg-light">
<div class="card-body">
<div class="d-flex align-items-center gap-2 mb-2">
<span class="badge bg-secondary"><%= i %></span>
<input type="text" name="service_step_title[]" class="form-control form-control-sm" placeholder="Service <%= i %>" required />
</div>
<textarea name="service_step_desc[]" class="form-control form-control-sm" rows="2" placeholder="Description" required></textarea>
</div>
</div>
</div>
<% } %>
</div>
</div>
</div>
</div>
<!-- Related Countries -->
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-globe me-2"></i>Related Countries (7)</h6>
</div>
<div class="card-body">
<div class="row g-3">
<% for(let i=0; i<7; i++) { %>
<div class="col-md-6">
<div class="card bg-light">
<div class="card-body">
<div class="row g-2">
<div class="col-md-7">
<label class="form-label fw-medium small">Country Name</label>
<input type="text" name="related_name[]" class="form-control form-control-sm" placeholder="e.g. Japan" required />
</div>
<div class="col-md-5">
<label class="form-label fw-medium small">Icon</label>
<div class="input-group input-group-sm">
<input type="text" name="related_icon[]" id="related_url_<%= i %>" class="form-control form-control-sm" placeholder="/uploads/visa/icon.png" required />
<input type="file" id="related_file_<%= i %>" class="d-none" accept="image/*">
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="document.getElementById('related_file_<%= i %>').click()">
<i class="fas fa-upload"></i>
</button>
</div>
<div style="margin-top: 5px;">
<img id="related_preview_<%= i %>" src="" alt="preview" style="max-width: 60px; max-height: 60px; object-fit: contain; display: none; border-radius: 4px; border: 1px solid #ddd;">
</div>
</div>
</div>
</div>
</div>
</div>
<% } %>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tab 3: Contact -->
<div class="tab-pane fade" id="tab-contact" role="tabpanel">
<div class="row g-3">
<div class="col-md-12">
<div class="card border shadow-sm">
<div class="card-header bg-white">
<h6 class="mb-0"><i class="fas fa-phone-alt me-2"></i>Contact Information</h6>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-12">
<label class="form-label fw-medium">Section Title</label>
<input type="text" name="contact_sectionTitle" class="form-control" placeholder="e.g. Visa & Immigration" required/>
</div>
<div class="col-md-12">
<label class="form-label fw-medium">Help Text</label>
<input type="text" name="contact_helpText" class="form-control" placeholder="e.g. Need Help?" required/>
</div>
<div class="col-md-4">
<label class="form-label fw-medium">Phone Label</label>
<input type="text" name="contact_phone_label" class="form-control" placeholder="Call Us" required />
<label class="form-label fw-medium mt-2">Phone Number</label>
<input type="text" name="contact_phone" class="form-control" placeholder="+009 438 222 9540" required />
</div>
<div class="col-md-4">
<label class="form-label fw-medium">Email Label</label>
<input type="text" name="contact_email_label" class="form-control" placeholder="Mail Us" required />
<label class="form-label fw-medium mt-2">Email Address</label>
<input type="email" name="contact_email" class="form-control" placeholder="info@example.com" required />
</div>
<div class="col-md-4">
<label class="form-label fw-medium">Location Label</label>
<input type="text" name="contact_location_label" class="form-control" placeholder="Location" required />
<label class="form-label fw-medium mt-2">Address</label>
<input type="text" name="contact_location" class="form-control" placeholder="City, Country" required />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="card-footer bg-light d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-secondary" id="btnBackToList">
<i class="fas fa-arrow-left me-2"></i>Back to List
</button>
<button type="submit" form="formCountry" class="btn btn-primary">
<i class="fas fa-save me-2"></i>Save
</button>
</div>
</div>
<!-- View Info -->
<div class="card shadow-sm border-0 mb-4" id="viewContainer" style="display: none;">
<div class="card-header bg-white border-bottom">
<h6 class="mb-0">Country Information</h6>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label fw-medium">Country Name</label>
<div class="alert alert-light mb-0" id="view-name">-</div>
</div>
<div class="col-md-12">
<label class="form-label fw-medium">Services</label>
<div class="alert alert-light mb-0" id="view-services">-</div>
</div>
<div class="col-md-12">
<label class="form-label fw-medium">Description</label>
<div class="alert alert-light mb-0" id="view-description">-</div>
</div>
<div class="col-md-6">
<label class="form-label fw-medium">Phone</label>
<div class="alert alert-light mb-0" id="view-phone">-</div>
</div>
<div class="col-md-6">
<label class="form-label fw-medium">Email</label>
<div class="alert alert-light mb-0" id="view-email">-</div>
</div>
</div>
</div>
<div class="card-footer bg-light d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-secondary" id="btnBackFromView">
<i class="fas fa-arrow-left me-2"></i>Back to List
</button>
</div>
</div>
</div>
</div>
</div>
<script>
let countriesData = {};
// Image upload handler
function setupImageUploadHandlers() {
const imageInputs = ["fileFlagInput", "fileDetailMainInput", "fileGalleryInput1", "fileGalleryInput2"];
const previewMap = {
fileFlagInput: "preview_icon",
fileDetailMainInput: "preview_main_detail",
fileGalleryInput1: "preview_bannerImageGallery1",
fileGalleryInput2: "preview_bannerImageGallery2"
};
const inputMap = {
fileFlagInput: "icon_input",
fileDetailMainInput: "mainImage_detail",
fileGalleryInput1: "bannerImageGallery1",
fileGalleryInput2: "bannerImageGallery2"
};
imageInputs.forEach((fileId) => {
const fileEl = document.getElementById(fileId);
if (!fileEl) return;
fileEl.addEventListener("change", function () {
const file = this.files[0];
if (!file) return;
if (!file.type.startsWith('image/')) {
showNotification('Please select a valid image file (JPG, PNG, GIF, etc.)', 'error');
return;
}
// Show preview immediately with base64
const reader = new FileReader();
const previewId = previewMap[fileId];
const preview = document.getElementById(previewId);
reader.onload = function (e) {
if (preview) {
preview.src = e.target.result;
preview.style.display = "block";
}
};
reader.readAsDataURL(file);
if (typeof uploadImageToServer === "function") {
uploadImageToServer(file, fileId, inputMap[fileId], previewId);
}
});
});
}
function uploadImageToServer(file, fileId, inputId, previewId) {
const formData = new FormData();
formData.append('image', file);
formData.append('imageType', 'visa');
fetch('/admin/upload/image?imageType=visa', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
const inputField = document.getElementById(inputId);
if (inputField) {
inputField.value = data.path || `/uploads/visa/${file.name}`;
}
// Update preview image
const preview = document.getElementById(previewId);
if (preview) {
preview.src = data.path || `/uploads/visa/${file.name}`;
preview.style.display = "block";
}
} else {
showNotification('Upload error: ' + (data.error || 'Unknown error'), 'error');
}
})
.catch(error => {
console.error('Upload failed:', error);
showNotification('Connection error: ' + error.message, 'error');
});
}
document.addEventListener("DOMContentLoaded", function () {
for (let i = 0; i < 7; i++) {
const fileInput = document.getElementById(`related_file_${i}`);
if (fileInput) {
fileInput.addEventListener("change", function () {
const file = this.files[0];
const urlInput = document.getElementById(`related_url_${i}`);
const preview = document.getElementById(`related_preview_${i}`);
if (file) {
if (!file.type.startsWith('image/')) {
showNotification('Please select a valid image file (JPG, PNG, GIF, etc.)', 'error');
return;
}
// Show preview immediately with base64
const reader = new FileReader();
reader.onload = (e) => {
if (preview) {
preview.src = e.target.result;
preview.style.display = "block";
}
};
reader.readAsDataURL(file);
const formData = new FormData();
formData.append('image', file);
formData.append('imageType', 'visa');
fetch('/admin/upload/image?imageType=visa', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success && urlInput) {
urlInput.value = data.path || `/uploads/visa/${file.name}`;
// Update preview with server path
if (preview) {
preview.src = data.path || `/uploads/visa/${file.name}`;
}
}
})
.catch(error => {
console.error('Upload failed:', error);
});
}
});
}
}
setupImageUploadHandlers();
});
function showListView() {
document.getElementById("tableContainer").style.display = "block";
document.getElementById("formContainer").style.display = "none";
document.getElementById("viewContainer").style.display = "none";
}
function showFormView() {
document.getElementById("tableContainer").style.display = "none";
document.getElementById("formContainer").style.display = "block";
document.getElementById("viewContainer").style.display = "none";
}
function showViewView() {
document.getElementById("tableContainer").style.display = "none";
document.getElementById("formContainer").style.display = "none";
document.getElementById("viewContainer").style.display = "block";
}
function viewCountry(countryId) {
const country = countriesData[countryId];
if (country) {
document.getElementById("view-name").textContent = country.name || "-";
document.getElementById("view-services").textContent = country.services.join(", ") || "-";
if (country.detailedView && country.detailedView.activeCountry) {
const details = country.detailedView.activeCountry;
document.getElementById("view-description").textContent = details.description || "-";
document.getElementById("view-phone").textContent = details.contactInfo?.phone?.value || "-";
document.getElementById("view-email").textContent = details.contactInfo?.email?.value || "-";
}
showViewView();
}
}
async function editCountry(countryId) {
try {
const response = await fetch(`/admin/visa/edit/${countryId}`);
const result = await response.json();
if (!result.success) {
showNotification('Error: ' + result.error, 'error');
return;
}
const country = result.country;
document.getElementById("country_id").value = country.id;
document.querySelector('input[name="name"]').value = country.name || "";
document.getElementById("icon_input").value = country.icon || "";
// Update icon preview
if (country.icon) {
const iconPreview = document.getElementById("preview_icon");
if (iconPreview) {
iconPreview.src = country.icon;
iconPreview.style.display = "block";
}
}
const serviceInputs = document.querySelectorAll('input[name="services[]"]');
serviceInputs.forEach(input => input.value = "");
if (country.services) {
country.services.forEach((service, index) => {
if (serviceInputs[index]) serviceInputs[index].value = service;
});
}
const details = country.detailedView?.activeCountry;
if (details) {
document.querySelector('input[name="detail_title"]').value = details.title || "";
document.getElementById("mainImage_detail").value = details.mainImage || "";
// Update preview for main image
if (details.mainImage) {
const mainPreview = document.getElementById("preview_main_detail");
if (mainPreview) {
mainPreview.src = details.mainImage;
mainPreview.style.display = "block";
}
}
document.querySelector('textarea[name="description"]').value = details.description || "";
document.querySelector('textarea[name="additionalInfo"]').value = details.additionalInfo || "";
document.querySelector('input[name="tagline"]').value = details.tagline || "";
if (details.visaTypes) {
for(let i=1; i<=4; i++) {
const typeIdx = Math.floor((i-1)/2);
const itemIdx = (i-1) % 2;
document.querySelector(`input[name="visa_title_${i}"]`).value = details.visaTypes[typeIdx]?.items[itemIdx]?.title || "";
document.querySelector(`textarea[name="visa_desc_${i}"]`).value = details.visaTypes[typeIdx]?.items[itemIdx]?.description || "";
}
}
document.querySelector('input[name="process_title"]').value = details.visaProcess?.title || "";
const stepTitles = document.querySelectorAll('input[name="step_title[]"]');
const stepDescs = document.querySelectorAll('textarea[name="step_desc[]"]');
stepTitles.forEach(i => i.value = "");
stepDescs.forEach(i => i.value = "");
if (details.visaProcess?.steps) {
details.visaProcess.steps.forEach((step, index) => {
if (stepTitles[index]) stepTitles[index].value = step.title || "";
if (stepDescs[index]) stepDescs[index].value = step.description || "";
});
}
const galleryData = details.gallery || [];
const galleryInputs = document.querySelectorAll('input[name="bannerImageGallery"]');
galleryInputs.forEach((input, index) => {
input.value = galleryData[index] || "";
// Update gallery preview images
const previewId = `preview_bannerImageGallery${index + 1}`;
const preview = document.getElementById(previewId);
if (preview && galleryData[index]) {
preview.src = galleryData[index];
preview.style.display = "block";
}
});
const categories = details.visaCategories;
document.querySelector('input[name="visa_categories_title"]').value = categories?.title || "";
const group1Inputs = document.querySelectorAll('input[name="category_group1[]"]');
const group2Inputs = document.querySelectorAll('input[name="category_group2[]"]');
if (categories && Array.isArray(categories.steps)) {
const g1 = categories.steps[0];
if (g1) {
for (let i = 0; i <= 2; i++) {
if (group1Inputs[i]) group1Inputs[i].value = g1[i] || "";
}
}
const g2 = categories.steps[1];
if (g2) {
for (let i = 0; i <= 1; i++) {
if (group2Inputs[i]) group2Inputs[i].value = g2[i] || "";
}
}
}
const serviceOptions = details.visaService;
document.querySelector('input[name="service_main_title"]').value = serviceOptions?.title || "";
const serviceStepTitles = document.querySelectorAll('input[name="service_step_title[]"]');
const serviceStepDescs = document.querySelectorAll('textarea[name="service_step_desc[]"]');
const servicesData = serviceOptions?.steps || [];
serviceStepTitles.forEach((inputEl, index) => {
const stepData = servicesData[index];
inputEl.value = stepData?.title || "";
if (serviceStepDescs[index]) {
serviceStepDescs[index].value = stepData?.description || "";
}
});
const relatedCountries = country.detailedView?.relatedCountries || [];
const relatedNameInputs = document.querySelectorAll('input[name="related_name[]"]');
const relatedIconInputs = document.querySelectorAll('input[name="related_icon[]"]');
relatedNameInputs.forEach(input => input.value = "");
relatedIconInputs.forEach(input => input.value = "");
relatedCountries.forEach((country, index) => {
if (index < 7) {
if (relatedNameInputs[index]) relatedNameInputs[index].value = country.name || "";
if (relatedIconInputs[index]) relatedIconInputs[index].value = country.icon || "";
// Update related country preview images
const preview = document.getElementById(`related_preview_${index}`);
if (preview && country.icon) {
preview.src = country.icon;
preview.style.display = "block";
}
}
});
const contactInfo = country.detailedView?.contactInfo;
if (contactInfo) {
document.querySelector('input[name="contact_sectionTitle"]').value = contactInfo.sectionTitle || "";
document.querySelector('input[name="contact_helpText"]').value = contactInfo.helpText || "";
document.querySelector('input[name="contact_phone_label"]').value = contactInfo.phone?.label || "";
document.querySelector('input[name="contact_phone"]').value = contactInfo.phone?.value || "";
document.querySelector('input[name="contact_email_label"]').value = contactInfo.email?.label || "";
document.querySelector('input[name="contact_email"]').value = contactInfo.email?.value || "";
document.querySelector('input[name="contact_location_label"]').value = contactInfo.location?.label || "";
document.querySelector('input[name="contact_location"]').value = contactInfo.location?.address || "";
}
}
showFormView();
} catch (error) {
console.error("Error:", error);
showNotification('Cannot connect to server. Please try again.', 'error');
}
}
async function deleteCountry(countryId) {
const confirmModal = document.createElement('div');
confirmModal.id = 'deleteConfirmModal';
confirmModal.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: flex; justify-content: center; align-items: center; z-index: 9999;';
confirmModal.innerHTML = `
<div style="background: white; padding: 25px; border-radius: 8px; max-width: 380px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); border-left: 4px solid #d9534f;">
<h5 style="color: #d9534f; margin: 0 0 15px 0; font-size: 16px; font-weight: 600;">Delete Country</h5>
<p style="color: #666; margin-bottom: 25px; font-size: 14px; line-height: 1.5;">Are you sure you want to delete this country? This action cannot be undone.</p>
<div style="display: flex; gap: 10px; justify-content: flex-end;">
<button class="cancelBtn" onclick="document.getElementById('deleteConfirmModal').remove()" style="padding: 10px 18px; border: 1px solid #ddd; background: #f5f5f5; color: #333; border-radius: 4px; cursor: pointer; font-weight: 500; font-size: 14px;">Cancel</button>
<button class="deleteBtn" onclick="performDelete(${countryId})" style="padding: 10px 18px; background: #d9534f; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500; font-size: 14px;">Delete</button>
</div>
</div>
`;
document.body.appendChild(confirmModal);
}
async function performDelete(countryId) {
const confirmModal = document.getElementById('deleteConfirmModal');
const deleteBtn = confirmModal.querySelector('.deleteBtn');
const cancelBtn = confirmModal.querySelector('.cancelBtn');
deleteBtn.disabled = true;
cancelBtn.disabled = true;
deleteBtn.style.opacity = '0.6';
deleteBtn.innerHTML = '<span style="display: inline-block; width: 12px; height: 12px; border: 2px solid white; border-top: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; margin-right: 5px;"></span>Deleting...';
try {
const response = await fetch(`/admin/visa/delete/${countryId}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (result.success) {
confirmModal.remove();
showNotification(result.message || 'Country deleted successfully!', 'success');
setTimeout(() => location.reload(), 1500);
} else {
deleteBtn.disabled = false;
cancelBtn.disabled = false;
deleteBtn.style.opacity = '1';
deleteBtn.innerHTML = 'Delete';
showNotification('Error: ' + (result.error || 'Cannot delete this country'), 'error');
}
} catch (error) {
console.error("Error:", error.message);
deleteBtn.disabled = false;
cancelBtn.disabled = false;
deleteBtn.style.opacity = '1';
deleteBtn.innerHTML = 'Delete';
showNotification('Connection error: ' + error.message, 'error');
}
}
document.getElementById("btnAddCountry").addEventListener("click", function () {
document.getElementById("formCountry").reset();
document.getElementById("country_id").value = "";
// Clear all preview images
document.getElementById("preview_icon").style.display = "none";
document.getElementById("preview_main_detail").style.display = "none";
document.getElementById("preview_bannerImageGallery1").style.display = "none";
document.getElementById("preview_bannerImageGallery2").style.display = "none";
// Clear related countries previews
for (let i = 0; i < 7; i++) {
const preview = document.getElementById(`related_preview_${i}`);
if (preview) {
preview.style.display = "none";
preview.src = "";
}
}
const relatedNameInputs = document.querySelectorAll('input[name="related_name[]"]');
const relatedIconInputs = document.querySelectorAll('input[name="related_icon[]"]');
relatedNameInputs.forEach(input => input.value = "");
relatedIconInputs.forEach(input => input.value = "");
const contactFields = ["contact_sectionTitle", "contact_helpText", "contact_phone_label", "contact_phone", "contact_email_label", "contact_email", "contact_location_label", "contact_location"];
contactFields.forEach(fieldName => {
const field = document.querySelector(`input[name="${fieldName}"]`);
if (field) field.value = "";
});
showFormView();
});
document.getElementById("btnBackToList").addEventListener("click", showListView);
document.getElementById("btnBackFromView").addEventListener("click", showListView);
document.getElementById('formCountry').addEventListener('submit', async function (e) {
e.preventDefault();
// Validate required fields
const requiredInputs = document.querySelectorAll('#formCountry input[required], #formCountry textarea[required]');
let emptyFields = [];
requiredInputs.forEach(input => {
if (!input.value || input.value.trim() === '') {
const label = input.parentElement.querySelector('.form-label')?.textContent || input.name;
emptyFields.push(label);
}
});
if (emptyFields.length > 0) {
showNotification(`Please fill in all required fields: ${emptyFields.join(', ')}`, 'warning');
return;
}
const btnSave = document.querySelector('.btn-primary');
const countryId = document.getElementById("country_id").value;
const galleryArray = Array.from(document.querySelectorAll('input[name="bannerImageGallery"]'))
.map(input => input.value)
.filter(url => url.trim() !== "");
const serviceSteps = Array.from(document.querySelectorAll('input[name="service_step_title[]"]'))
.map((input, index) => {
const title = input.value.trim();
const description = document.querySelectorAll('textarea[name="service_step_desc[]"]')[index].value.trim();
return title ? { title, description } : null;
})
.filter(item => item !== null);
const payload = {
id: countryId || null,
name: document.querySelector('input[name="name"]').value,
icon: document.querySelector('input[name="icon"]').value,
services: Array.from(document.querySelectorAll('input[name="services[]"]')).map(i => i.value),
detailedView: {
activeCountry: {
id: countryId || null,
title: document.querySelector('input[name="detail_title"]').value,
mainImage: document.getElementById('mainImage_detail').value || "",
description: document.querySelector('textarea[name="description"]').value,
additionalInfo: document.querySelector('textarea[name="additionalInfo"]').value,
tagline: document.querySelector('input[name="tagline"]').value,
visaTypes: [
{
items: [
{ title: document.querySelector('input[name="visa_title_1"]').value, description: document.querySelector('textarea[name="visa_desc_1"]').value },
{ title: document.querySelector('input[name="visa_title_2"]').value, description: document.querySelector('textarea[name="visa_desc_2"]').value }
]
},
{
items: [
{ title: document.querySelector('input[name="visa_title_3"]').value, description: document.querySelector('textarea[name="visa_desc_3"]').value },
{ title: document.querySelector('input[name="visa_title_4"]').value, description: document.querySelector('textarea[name="visa_desc_4"]').value }
]
}
],
visaProcess: {
title: document.querySelector('input[name="process_title"]').value,
steps: Array.from(document.querySelectorAll('input[name="step_title[]"]')).map((input, index) => ({
title: input.value,
description: document.querySelectorAll('textarea[name="step_desc[]"]')[index].value
}))
},
gallery: galleryArray,
visaCategories: {
title: document.querySelector('input[name="visa_categories_title"]').value,
steps: [
Array.from(document.querySelectorAll('input[name="category_group1[]"]')).map(input => input.value),
Array.from(document.querySelectorAll('input[name="category_group2[]"]')).map(input => input.value)
]
},
visaService: {
title: document.querySelector('input[name="service_main_title"]').value.trim(),
steps: serviceSteps
}
},
relatedCountries: Array.from({ length: 7 }).map((_, index) => ({
name: document.querySelectorAll('input[name="related_name[]"]')[index]?.value || "",
icon: document.getElementById(`related_url_${index}`)?.value || ""
})),
contactInfo: {
sectionTitle: document.querySelector('input[name="contact_sectionTitle"]').value,
helpText: document.querySelector('input[name="contact_helpText"]').value,
phone: {
label: document.querySelector('input[name="contact_phone_label"]').value,
value: document.querySelector('input[name="contact_phone"]').value
},
email: {
label: document.querySelector('input[name="contact_email_label"]').value,
value: document.querySelector('input[name="contact_email"]').value
},
location: {
label: document.querySelector('input[name="contact_location_label"]').value,
address: document.querySelector('input[name="contact_location"]').value
}
}
}
};
try {
btnSave.disabled = true;
btnSave.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Saving...';
const method = countryId ? 'PUT' : 'POST';
const url = countryId ? `/admin/visa/update/${countryId}` : '/admin/visa/add';
const response = await fetch(url, {
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const result = await response.json();
if (result.success) {
showNotification('Country saved successfully!', 'success');
setTimeout(() => location.reload(), 1500);
} else {
throw new Error(result.error || "Unknown error");
}
} catch (err) {
showNotification('Error: ' + err.message, 'error');
} finally {
btnSave.disabled = false;
btnSave.innerHTML = '<i class="fas fa-save me-2"></i>Save';
}
});
</script>