fix payment
This commit is contained in:
1 parent
4f7486152c
commit
bb3ddd1610
47 files changed
+2137
-51
No files matched your search
@@ -48,7 +48,7 @@
|
||||
const data = await response.json();
|
||||
if (request !== controller || customer.value !== selectedCustomer) return;
|
||||
if (!response.ok) {failureMessage = data.error || 'شناسه تولید نشد؛ دوباره تلاش کنید.'; throw new Error('generation');}
|
||||
if (data.customer !== selectedCustomer || !/^[0-9]{13}$/.test(data.identifier)) {failureMessage = 'پاسخ سیستم معتبر نیست؛ دوباره تلاش کنید.'; throw new Error('generation');}
|
||||
if (data.customer !== selectedCustomer || !/^9[0-9]{11}$/.test(data.identifier)) {failureMessage = 'پاسخ سیستم معتبر نیست؛ دوباره تلاش کنید.'; throw new Error('generation');}
|
||||
if (input.value.trim() && input.value !== data.identifier) {
|
||||
pending = data.identifier; candidate.textContent = pending; replacement.hidden = false;
|
||||
status.textContent = 'شناسه آماده است؛ برای جایگزینی مقدار فعلی، دکمه جایگزینی را بزنید.';
|
||||
|
||||
@@ -13,6 +13,22 @@ async function copy(text){
|
||||
}
|
||||
}
|
||||
document.querySelectorAll('[data-copy]').forEach(button=>button.addEventListener('click',()=>copy(button.dataset.copy)));
|
||||
document.querySelectorAll('[data-notice-sms]').forEach(form=>form.addEventListener('submit',event=>{
|
||||
if(form.dataset.sending==='true'){event.preventDefault();return;}
|
||||
form.dataset.sending='true';const button=form.querySelector('button');button.disabled=true;button.textContent='در حال ثبت درخواست ارسال…';
|
||||
}));
|
||||
document.querySelectorAll('[data-share-link]').forEach(form=>form.addEventListener('submit',async event=>{
|
||||
event.preventDefault();
|
||||
const button=form.querySelector('button'),feedback=form.querySelector('[role="status"]');
|
||||
button.disabled=true;button.setAttribute('aria-busy','true');feedback.textContent='در حال آمادهسازی لینک…';
|
||||
try{
|
||||
const response=await fetch(form.action,{method:'POST',body:new FormData(form),credentials:'same-origin',cache:'no-store',headers:{'Accept':'application/json'}});
|
||||
if(!response.ok || !response.headers.get('Content-Type')?.includes('application/json'))throw new Error('share unavailable');
|
||||
const data=await response.json();
|
||||
await copy(data.url);feedback.textContent='لینک آماده است؛ میتوانید آن را برای دیگران ارسال کنید.';
|
||||
}catch{feedback.textContent='دریافت لینک ممکن نشد. دوباره تلاش کنید یا لینک پرداخت دریافتی را باز کنید.';}
|
||||
finally{button.disabled=false;button.removeAttribute('aria-busy');}
|
||||
}));
|
||||
const identifiers=document.querySelector('#identifier-accounts'),account=document.querySelector('#id_account'),deposit=document.querySelector('#id_deposit_id');
|
||||
if(identifiers && account && deposit){const ids=JSON.parse(identifiers.textContent).map(String);function update(){deposit.required=ids.includes(account.value);document.querySelector('#identifier-help').textContent=deposit.required?'این حساب شناسهدار است؛ شناسه واریز مشتری الزامی است.':'شناسه واریز در صورت اعلام بانک وارد شود.';}account.addEventListener('change',update);update();}
|
||||
const badge=document.querySelector('[data-payment-count]');
|
||||
|
||||
@@ -42,8 +42,8 @@ fields.forEach(field=>{const controls=field.querySelectorAll('input,select,texta
|
||||
let busy=false;
|
||||
function showErrors(errors){
|
||||
fields.forEach(field=>{const name=field.dataset.field,message=errors.get(name)||'',error=field.querySelector('.field-error');error.textContent=message;error.hidden=!message;field.querySelectorAll('input,select,textarea').forEach(control=>control.setAttribute('aria-invalid',String(Boolean(message))));});
|
||||
const summary=document.querySelector('#receipt-errors'),list=summary.querySelector('ul');list.replaceChildren();errors.forEach((message,name)=>{const item=document.createElement('li'),link=document.createElement('a');link.href='#id_'+name;link.textContent=message;link.onclick=event=>{event.preventDefault();q(name).focus();q(name).scrollIntoView({block:'center'});};item.append(link);list.append(item);});summary.hidden=!errors.size;
|
||||
if(errors.size){const first=q(errors.keys().next().value);first.focus();first.scrollIntoView({block:'center'});}
|
||||
const summary=document.querySelector('#receipt-errors'),list=summary.querySelector('ul');list.replaceChildren();errors.forEach((message,name)=>{const item=document.createElement('li'),control=q(name);if(control && typeof control.focus==='function'){const link=document.createElement('a');link.href='#'+control.id;link.textContent=message;link.onclick=event=>{event.preventDefault();control.focus();control.scrollIntoView({block:'center'});};item.append(link);}else item.textContent=message;list.append(item);});summary.hidden=!errors.size;
|
||||
if(errors.size){const first=q(errors.keys().next().value);if(first && typeof first.focus==='function'){first.focus();first.scrollIntoView({block:'center'});}else{summary.tabIndex=-1;summary.focus();summary.scrollIntoView({block:'center'});}}
|
||||
}
|
||||
async function validateImage(file){
|
||||
if(!file)return 'تصویر فیش واریز را انتخاب کنید.';
|
||||
@@ -53,7 +53,7 @@ async function validateImage(file){
|
||||
}
|
||||
let revision=0;form.addEventListener('input',()=>revision++);form.addEventListener('change',()=>revision++);
|
||||
form.addEventListener('submit',async event=>{
|
||||
event.preventDefault();if(busy)return;busy=true;button.disabled=true;const version=revision,errors=new Map();
|
||||
event.preventDefault();if(busy)return;busy=true;button.disabled=true;button.textContent='در حال بررسی تصویر…';document.querySelector('#form-status').textContent='';const version=revision,errors=new Map();let navigating=false;
|
||||
try{
|
||||
const value=digits(q('paid_amount').value).trim();if(!/^\d+$/.test(value) && !/^\d{1,3}(?:[,٬ ]\d{3})+$/.test(value))errors.set('paid_amount','مبلغ را به ریال و با عدد صحیح وارد کنید.');else{const amount=BigInt(value.replace(/[,٬ ]/g,''));if(amount<=0n || amount>9007199254740991n)errors.set('paid_amount','مبلغ باید مثبت و در محدوده مجاز باشد.');}
|
||||
if(q('receipt_mode').value==='linked' && !q('notice_id').value)errors.set('notice_id','اعلامیه را انتخاب کنید یا واریز مستقل را بزنید.');
|
||||
@@ -63,8 +63,11 @@ form.addEventListener('submit',async event=>{
|
||||
const imageError=await validateImage(q('receipt_image').files[0]);if(imageError)errors.set('receipt_image',imageError);
|
||||
if(version!==revision){document.querySelector('#form-status').textContent='اطلاعات تغییر کرده است؛ دوباره ارسال را بزنید.';return;}
|
||||
showErrors(errors);if(errors.size)return;
|
||||
button.textContent='در حال ثبت…';HTMLFormElement.prototype.submit.call(form);return;
|
||||
}finally{busy=false;if(button.textContent!=='در حال ثبت…')button.disabled=false;}
|
||||
const result=await window.ReceiptUpload.send(form);
|
||||
if(result.redirect_url){const destination=new URL(result.redirect_url,location.href);if(destination.origin!==location.origin)throw new Error('پاسخ ثبت فیش معتبر نیست.');navigating=true;location.assign(destination.href);return;}
|
||||
showErrors(new Map(Object.entries(result.errors).map(([name,items])=>[name,items.map(item=>item.message).join(' ')])));
|
||||
}catch(error){showErrors(new Map([['__all__',error.message || 'ارسال فیش انجام نشد؛ دوباره تلاش کنید.']]));}
|
||||
finally{if(!navigating){busy=false;button.disabled=false;button.textContent='ثبت و ارسال فیش';}}
|
||||
});
|
||||
if(document.querySelector('#receipt-errors').hidden===false){const field=form.querySelector('[aria-invalid=true]');if(field){field.focus();field.scrollIntoView({block:'center'});}}
|
||||
})();
|
||||
@@ -0,0 +1,65 @@
|
||||
/* Real multipart upload progress; registration remains authoritative on the server. */
|
||||
(() => {
|
||||
'use strict';
|
||||
const number=new Intl.NumberFormat('fa-IR',{maximumFractionDigits:1});
|
||||
function bytes(value){return value>=1048576?number.format(value/1048576)+' مگابایت':number.format(value/1024)+' کیلوبایت';}
|
||||
function duration(seconds){return seconds>=60?number.format(Math.ceil(seconds/60))+' دقیقه':number.format(Math.max(1,Math.ceil(seconds)))+' ثانیه';}
|
||||
function send(form){
|
||||
const payload=new FormData(form),panel=document.querySelector('#receipt-upload');
|
||||
const title=document.querySelector('#receipt-upload-title'),meter=document.querySelector('#receipt-upload-progress');
|
||||
const percent=document.querySelector('#receipt-upload-percent'),amount=document.querySelector('#receipt-upload-bytes'),time=document.querySelector('#receipt-upload-time');
|
||||
const button=document.querySelector('#submit-receipt');
|
||||
const controls=[...form.querySelectorAll('input,select,textarea,button')].map(control=>[control,control.disabled]);
|
||||
controls.forEach(([control])=>{control.disabled=true;});form.classList.add('is-uploading');button.setAttribute('aria-busy','true');
|
||||
panel.hidden=false;title.textContent='در حال ارسال فیش…';button.textContent='در حال ارسال…';
|
||||
meter.value=0;percent.textContent='۰٪';amount.textContent='در انتظار شروع ارسال';
|
||||
const started=performance.now();let loaded=0,total=0,lastProgress=started,processing=false;
|
||||
function updateTime(){
|
||||
if(processing)return;
|
||||
const elapsed=(performance.now()-started)/1000;
|
||||
const estimate=loaded>0 && elapsed>=1 && total>loaded;
|
||||
time.textContent='زمان سپریشده: '+number.format(Math.floor(elapsed))+' ثانیه'+(performance.now()-lastProgress>5000?' · منتظر ادامه ارسال؛ سرعت اتصال تغییر کرده است.':estimate?' · حدود '+duration((total-loaded)*elapsed/loaded)+' دیگر برای ارسال':' · در حال محاسبه زمان باقیمانده…');
|
||||
}
|
||||
function process(){
|
||||
processing=true;meter.value=100;percent.textContent='۱۰۰٪';
|
||||
title.textContent='ارسال کامل شد؛ در حال بررسی و ثبت فیش…';button.textContent='در حال ثبت…';
|
||||
time.textContent='منتظر تأیید ثبت از سرور؛ زمان این مرحله به سرعت پردازش بستگی دارد.';
|
||||
}
|
||||
updateTime();panel.scrollIntoView({block:'nearest'});
|
||||
return new Promise((resolve,reject)=>{
|
||||
const xhr=new XMLHttpRequest(),timer=setInterval(updateTime,1000);let settled=false;
|
||||
function finish(error,result){
|
||||
if(settled)return;settled=true;clearInterval(timer);
|
||||
if(!result?.redirect_url){
|
||||
controls.forEach(([control,disabled])=>{control.disabled=disabled;});form.classList.remove('is-uploading');button.removeAttribute('aria-busy');
|
||||
title.textContent='ثبت فیش انجام نشد';time.textContent='اطلاعات و تصویر حفظ شدهاند؛ پس از رفع مشکل دوباره ارسال کنید.';
|
||||
}
|
||||
if(error)reject(error);else resolve(result);
|
||||
}
|
||||
xhr.upload.addEventListener('progress',event=>{
|
||||
loaded=event.loaded;total=event.lengthComputable?event.total:0;lastProgress=performance.now();
|
||||
amount.textContent='ارسالشده: '+bytes(loaded)+(total?' از '+bytes(total):'');
|
||||
if(total){const value=Math.min(100,Math.floor(loaded/total*100));meter.value=value;percent.textContent=number.format(value)+'٪';}
|
||||
else{meter.removeAttribute('value');percent.textContent='در حال ارسال';}
|
||||
updateTime();
|
||||
});
|
||||
xhr.upload.addEventListener('load',process);
|
||||
xhr.addEventListener('load',()=>{
|
||||
const result=xhr.response;
|
||||
if(xhr.status>=200 && xhr.status<300 && result?.redirect_url){finish(null,result);return;}
|
||||
if(xhr.status===422 && result?.errors){finish(null,result);return;}
|
||||
const message=[401,403,410].includes(xhr.status)?'دسترسی یا نشست شما معتبر نیست؛ صفحه را دوباره باز کنید.':xhr.status===413?'حجم تصویر بیش از حد مجاز سرور است؛ تصویر کوچکتری انتخاب کنید.':'ثبت فیش تأیید نشد؛ دوباره تلاش کنید. در صورت تکرار، وضعیت فیشهای خود را بررسی کنید.';
|
||||
finish(new Error(message));
|
||||
});
|
||||
xhr.addEventListener('error',()=>finish(new Error('ارتباط با سرور قطع شد؛ اتصال اینترنت را بررسی و دوباره ارسال کنید.')));
|
||||
xhr.addEventListener('abort',()=>finish(new Error('ارسال متوقف شد؛ دوباره تلاش کنید.')));
|
||||
try{
|
||||
xhr.open('POST',form.action || location.href);xhr.responseType='json';
|
||||
xhr.setRequestHeader('Accept','application/json');
|
||||
xhr.setRequestHeader('X-CSRFToken',payload.get('csrfmiddlewaretoken'));
|
||||
xhr.send(payload);
|
||||
}catch(error){finish(error);}
|
||||
});
|
||||
}
|
||||
window.ReceiptUpload=Object.freeze({send});
|
||||
})();
|
||||
Reference in new issue
Block a user