m
This commit is contained in:
@@ -85,6 +85,7 @@ $tpls = [
|
||||
<option value="{{$u->msnv}}">{{$u->name}} - {{$u->msnv}} ({{$u->mail}}) - {{$dept}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span id="error-receiver" class="text-red-500 text-[12px] font-semibold mt-1.5 hidden block"></span>
|
||||
</div>
|
||||
|
||||
{{-- Số lượng --}}
|
||||
@@ -100,16 +101,20 @@ $tpls = [
|
||||
</select>
|
||||
<span class="text-[12px] text-gray-400 font-medium">/ tháng</span>
|
||||
</div>
|
||||
<span id="error-amount" class="text-red-500 text-[12px] font-semibold mt-1.5 hidden block"></span>
|
||||
</div>
|
||||
|
||||
{{-- Confirm checkbox --}}
|
||||
<label class="flex items-start gap-3 p-4 rounded-2xl border border-[#e8edf4] bg-white/70 hover:bg-white/90 transition-colors cursor-pointer mb-2">
|
||||
<input type="checkbox" name="confirm_written" id="confirm_written" value="1"
|
||||
class="w-4 h-4 mt-0.5 text-[#3462f7] border-[#d9dfe7] rounded focus:ring-[#3462f7]/20 cursor-pointer shrink-0" required>
|
||||
<span class="text-[13px] font-medium text-gray-600 leading-relaxed select-none">
|
||||
Tôi xác nhận đã viết nội dung trên ThankCard và sẵn sàng gửi đến người nhận. <span class="text-[#3462f7] font-bold">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<div class="mb-2">
|
||||
<label class="flex items-start gap-3 p-4 rounded-2xl border border-[#e8edf4] bg-white/70 hover:bg-white/90 transition-colors cursor-pointer">
|
||||
<input type="checkbox" name="confirm_written" id="confirm_written" value="1"
|
||||
class="w-4 h-4 mt-0.5 text-[#3462f7] border-[#d9dfe7] rounded focus:ring-[#3462f7]/20 cursor-pointer shrink-0" required>
|
||||
<span class="text-[13px] font-medium text-gray-600 leading-relaxed select-none">
|
||||
Tôi xác nhận đã viết nội dung trên ThankCard và sẵn sàng gửi đến người nhận. <span class="text-[#3462f7] font-bold">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<span id="error-confirm_written" class="text-red-500 text-[12px] font-semibold mt-1.5 hidden block"></span>
|
||||
</div>
|
||||
|
||||
{{-- Card footer line --}}
|
||||
<div class="mt-6 pt-4 border-t border-dashed" id="cardFooterLine" style="border-color:#FFE4A0;">
|
||||
@@ -132,6 +137,14 @@ $tpls = [
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- General Error notification block -->
|
||||
<div id="formGeneralError" class="p-4 bg-red-50 border border-red-100 text-red-800 rounded-2xl text-xs font-semibold leading-relaxed flex items-start gap-2 shadow-sm mb-5 hidden">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5 shrink-0 text-red-600">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
<span id="generalErrorMessage"></span>
|
||||
</div>
|
||||
|
||||
{{-- Actions --}}
|
||||
<div class="flex flex-col sm:flex-row justify-end gap-3">
|
||||
<a href="{{ route('user.dashboard') }}" id="btnCancelLink" class="btn-secondary rounded-xl font-bold flex items-center justify-center gap-2 order-2 sm:order-1">
|
||||
@@ -186,8 +199,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
footerBorder:'#DDD6FE'},
|
||||
};
|
||||
|
||||
// ── Theme slugs ──────────────────────────────────────────────────
|
||||
const templateSlugs = {
|
||||
1: 'thu_cam_on',
|
||||
2: 'sakura',
|
||||
3: 'appreciation',
|
||||
4: 'celebration'
|
||||
};
|
||||
const templateIds = {
|
||||
'thu_cam_on': 1,
|
||||
'sakura': 2,
|
||||
'appreciation': 3,
|
||||
'celebration': 4
|
||||
};
|
||||
|
||||
// Current selected template ID (defaults to 1) // read from hidden input or localStorage
|
||||
let currentTpl = parseInt(localStorage.getItem('selectedTemplate')) || parseInt(document.getElementById('template_id').value) || 1;
|
||||
const savedTemplateSlug = localStorage.getItem('thankcard_selected_template');
|
||||
let currentTpl = (savedTemplateSlug && templateIds[savedTemplateSlug])
|
||||
|| parseInt(localStorage.getItem('selectedTemplate'))
|
||||
|| parseInt(document.getElementById('template_id').value)
|
||||
|| 1;
|
||||
|
||||
function applyTheme(id) {
|
||||
const t = T[id]; if (!t) return;
|
||||
@@ -256,6 +287,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
document.getElementById('template_id').value = id;
|
||||
// persist selection
|
||||
localStorage.setItem('selectedTemplate', id);
|
||||
if (templateSlugs[id]) {
|
||||
localStorage.setItem('thankcard_selected_template', templateSlugs[id]);
|
||||
}
|
||||
applyTheme(id);
|
||||
};
|
||||
|
||||
@@ -299,7 +333,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
|
||||
// ── TomSelect ────────────────────────────────────────────────────
|
||||
new TomSelect('#receiver', {
|
||||
const receiverSelect = new TomSelect('#receiver', {
|
||||
create:false, searchField:['text','value'], maxOptions:10,
|
||||
sortField:{field:'text',direction:'asc'},
|
||||
placeholder:'Nhập tên hoặc mã nhân viên...',
|
||||
@@ -327,7 +361,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
$mTitle.textContent = title;
|
||||
$mMsg.innerHTML = msg.replace(/\n/g,'<br>');
|
||||
if (confirm) {
|
||||
$mTitle.className = 'text-lg font-bold text-primary';
|
||||
$mTitle.className = 'text-lg font-bold';
|
||||
// Sync text color with current template's accent color
|
||||
$mTitle.style.color = T[currentTpl].accent;
|
||||
// Use accent color of current template for confirm button background
|
||||
const accent = T[currentTpl].accent;
|
||||
$mAct.innerHTML = `<button id="btnOk" class="w-full sm:w-auto btn-primary !px-6 rounded-xl font-bold" style="background:${accent};border-color:${accent};">Xác nhận gửi</button>
|
||||
@@ -340,41 +376,149 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
} else {
|
||||
$mTitle.className = 'text-lg font-bold text-[#1a2b49]';
|
||||
$mTitle.style.color = ''; // reset style
|
||||
$mAct.innerHTML = `<button id="btnClose" class="w-full sm:w-auto btn-secondary !px-6 rounded-xl font-bold">Đóng</button>`;
|
||||
document.getElementById('btnClose').onclick = () => window.closeModal('customModal');
|
||||
}
|
||||
window.openModal('customModal');
|
||||
};
|
||||
|
||||
// ── Error Helpers ────────────────────────────────────────────────
|
||||
function clearErrors() {
|
||||
document.getElementById('formGeneralError').classList.add('hidden');
|
||||
document.getElementById('generalErrorMessage').textContent = '';
|
||||
|
||||
document.querySelectorAll('[id^="error-"]').forEach(el => {
|
||||
el.textContent = '';
|
||||
el.classList.add('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
function validateForm() {
|
||||
clearErrors();
|
||||
let isValid = true;
|
||||
|
||||
const receiver = document.getElementById('receiver').value;
|
||||
if (!receiver) {
|
||||
const errEl = document.getElementById('error-receiver');
|
||||
if (errEl) {
|
||||
errEl.textContent = 'Vui lòng chọn người nhận.';
|
||||
errEl.classList.remove('hidden');
|
||||
}
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
const amount = document.getElementById('amount').value;
|
||||
if (!amount) {
|
||||
const errEl = document.getElementById('error-amount');
|
||||
if (errEl) {
|
||||
errEl.textContent = 'Vui lòng chọn số lượng thẻ.';
|
||||
errEl.classList.remove('hidden');
|
||||
}
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
const confirm = document.getElementById('confirm_written').checked;
|
||||
if (!confirm) {
|
||||
const errEl = document.getElementById('error-confirm_written');
|
||||
if (errEl) {
|
||||
errEl.textContent = 'Bạn cần xác nhận đã viết nội dung trên ThankCard.';
|
||||
errEl.classList.remove('hidden');
|
||||
}
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// ── Submit ───────────────────────────────────────────────────────
|
||||
document.getElementById('btnSubmitSend').addEventListener('click', function(){
|
||||
const form = document.getElementById('sendCardForm');
|
||||
if (!form.checkValidity()) { form.reportValidity(); return; }
|
||||
const $submitBtn = document.getElementById('btnSubmitSend');
|
||||
const btnOriginalHtml = $submitBtn.innerHTML;
|
||||
|
||||
function setButtonLoading(loading) {
|
||||
if (loading) {
|
||||
$submitBtn.disabled = true;
|
||||
$submitBtn.innerHTML = `<svg class="animate-spin h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg><span>⏳ Đang gửi...</span>`;
|
||||
} else {
|
||||
$submitBtn.disabled = false;
|
||||
$submitBtn.innerHTML = btnOriginalHtml;
|
||||
// Keep selected template button accent style synchronized
|
||||
const accent = T[currentTpl]?.accent;
|
||||
if (accent) {
|
||||
$submitBtn.style.background = accent;
|
||||
$submitBtn.style.borderColor = accent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$submitBtn.addEventListener('click', function(){
|
||||
if (!validateForm()) { return; }
|
||||
|
||||
const msnv = document.getElementById('receiver').value;
|
||||
const amount = document.getElementById('amount').value;
|
||||
|
||||
showModal('Xác nhận gửi Thank Card',
|
||||
'Đừng quên hoàn thành Thank Card của bạn nhé! Chúng mình sẽ gửi thông báo đến người nhận để họ đến khu vực nhận thư.',
|
||||
true, () => {
|
||||
window.closeModal('customModal');
|
||||
setButtonLoading(true);
|
||||
clearErrors();
|
||||
|
||||
$.ajax({
|
||||
url:'{{ route("user.store_send") }}', method:'POST', contentType:'application/json',
|
||||
headers:{'X-CSRF-TOKEN':$('meta[name="csrf-token"]').attr('content')},
|
||||
data:JSON.stringify({receiver:msnv,amount:amount}),
|
||||
success:function(res){
|
||||
if(res.success){
|
||||
var email=res.receiver_email; email="antv@runsystem.net";
|
||||
$.ajax({
|
||||
url:'{{ config("constants.CHATOPS_API_URL") }}', method:'POST', contentType:'application/json',
|
||||
data:JSON.stringify({message:"💌 Bạn nhận được một Thank Card mới!\nNhanh chân đến khu vực nhận thư để nhận ngay nhé!",userEmail:email,token:'{{ config("constants.CHATOPS_API_TOKEN") }}'}),
|
||||
complete:function(){localStorage.setItem('flash_success',res.message);window.location.href='{{ route("user.dashboard") }}';}
|
||||
});
|
||||
setButtonLoading(false);
|
||||
|
||||
// Reset form fields
|
||||
receiverSelect.clear();
|
||||
document.getElementById('amount').value = '1';
|
||||
document.getElementById('confirm_written').checked = false;
|
||||
|
||||
// Clear local storage for inputs (but not template)
|
||||
localStorage.removeItem('selectedReceiver');
|
||||
localStorage.removeItem('selectedAmount');
|
||||
|
||||
// Display toast message
|
||||
if (window.showToast) {
|
||||
window.showToast("🎉 ThankCard đã được gửi thành công!", "success");
|
||||
} else {
|
||||
alert("🎉 ThankCard đã được gửi thành công!");
|
||||
}
|
||||
} else {
|
||||
window.closeModal('customModal');
|
||||
setTimeout(()=>showModal('Lỗi Giao Dịch',res.message||'Có lỗi xảy ra.',false,null),350);
|
||||
setButtonLoading(false);
|
||||
if (res.errors) {
|
||||
for (const [field, messages] of Object.entries(res.errors)) {
|
||||
const errEl = document.getElementById('error-' + field);
|
||||
if (errEl) {
|
||||
errEl.textContent = messages.join(' ');
|
||||
errEl.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res.message) {
|
||||
document.getElementById('generalErrorMessage').textContent = res.message;
|
||||
document.getElementById('formGeneralError').classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
},
|
||||
error:function(xhr){
|
||||
window.closeModal('customModal');
|
||||
setTimeout(()=>showModal('Lỗi Hệ Thống',xhr.responseJSON?.message||'Không thể kết nối đến máy chủ.',false,null),350);
|
||||
setButtonLoading(false);
|
||||
const res = xhr.responseJSON;
|
||||
if (res && res.errors) {
|
||||
for (const [field, messages] of Object.entries(res.errors)) {
|
||||
const errEl = document.getElementById('error-' + field);
|
||||
if (errEl) {
|
||||
errEl.textContent = messages.join(' ');
|
||||
errEl.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
const errMsg = res?.message || 'Không thể kết nối đến máy chủ.';
|
||||
document.getElementById('generalErrorMessage').textContent = errMsg;
|
||||
document.getElementById('formGeneralError').classList.remove('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user