/* Local amount presentation: never convert rials to tomans for the server. Exact BigInt arithmetic; preserve fractional toman (one rial = one tenth toman). Shared with notice amounts; visible grouping does not replace server validation. */ (() => { 'use strict'; const input=document.querySelector('#id_paid_amount, #id_amount');if(!input)return; input.inputMode='numeric'; const words=document.querySelector('#amount-words'); const small=['صفر','یک','دو','سه','چهار','پنج','شش','هفت','هشت','نه','ده','یازده','دوازده','سیزده','چهارده','پانزده','شانزده','هفده','هجده','نوزده']; const tens=['','','بیست','سی','چهل','پنجاه','شصت','هفتاد','هشتاد','نود']; const hundreds=['','صد','دویست','سیصد','چهارصد','پانصد','ششصد','هفتصد','هشتصد','نهصد']; const scales=['','هزار','میلیون','میلیارد','تریلیون','کوادریلیون']; const ascii=value=>value.replace(/[۰-۹]/g,digit=>String(digit.charCodeAt(0)-1776)).replace(/[٠-٩]/g,digit=>String(digit.charCodeAt(0)-1632)); const digitCount=value=>(ascii(value).match(/\d/g) || []).length; const separators=/[,٬ \u00a0]/g; const grouped=value=>value.replace(/\B(?=(\d{3})+(?!\d))/g,'٬').replace(/\d/g,digit=>'۰۱۲۳۴۵۶۷۸۹'[digit]); function threeDigits(value){ const parts=[]; if(value>=100)parts.push(hundreds[Math.floor(value/100)]); const rest=value%100; if(rest && rest<20)parts.push(small[rest]); if(rest>=20){parts.push(tens[Math.floor(rest/10)]);if(rest%10)parts.push(small[rest%10]);} return parts.join(' و '); } function numberWords(value){ if(value===0n)return 'صفر'; const parts=[];let index=0; while(value>0n){ const group=Number(value%1000n); if(group){const text=group===1 && index===1?'هزار':threeDigits(group)+(scales[index]?' '+scales[index]:'');parts.unshift(text);} value/=1000n;index++; } return parts.join(' و '); } function tomanWords(rials){ const whole=rials/10n,fraction=rials%10n; if(!fraction)return numberWords(whole)+' تومان'; return (whole?numberWords(whole)+' و ':'')+numberWords(fraction)+' دهم تومان'; } function caretAfterDigits(value,count){ if(!count)return 0; for(let index=0;index16 || BigInt(digits)>BigInt(Number.MAX_SAFE_INTEGER)){if(words)words.textContent='';return;} const leading=normalized.replace(separators,'').length-digits.length; const left=Math.max(0,digitCount(raw.slice(0,start))-leading),right=Math.max(0,digitCount(raw.slice(0,end))-leading); input.value=grouped(digits); input.setSelectionRange(caretAfterDigits(input.value,left),caretAfterDigits(input.value,right)); if(words)words.textContent='معادل: '+tomanWords(BigInt(digits)); } input.addEventListener('input',formatAmount); input.addEventListener('compositionend',()=>formatAmount()); input.addEventListener('beforeinput',event=>{ const start=input.selectionStart,end=input.selectionEnd; if(start!==end || event.isComposing)return; const backward=event.inputType==='deleteContentBackward',forward=event.inputType==='deleteContentForward'; const adjacent=backward?start-1:start; if((!backward && !forward) || !/[٬,]/.test(input.value[adjacent] || ''))return; // Deleting a separator removes the adjacent digit, so grouping cannot trap the caret. const target=backward?adjacent-1:adjacent+1; const count=digitCount(input.value.slice(0,target)); const raw=input.value.slice(0,target)+input.value.slice(target+1); event.preventDefault();input.value=ascii(raw).replace(separators,''); input.setSelectionRange(count,count);input.dispatchEvent(new InputEvent('input',{bubbles:true,inputType:event.inputType})); }); input.addEventListener('blur',()=>formatAmount()); formatAmount(); })();