stat2025 commited on
Commit
4c7f453
·
verified ·
1 Parent(s): c08d4b4

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +126 -1
app.js CHANGED
@@ -182,4 +182,129 @@ document.addEventListener("input",(e)=>{
182
  });
183
 
184
  /* Toast */
185
- function toast(ms
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  });
183
 
184
  /* Toast */
185
+ function toast(msg){
186
+ const t = document.getElementById("toast");
187
+ t.textContent = msg; t.hidden = false;
188
+ t.classList.remove("show"); void t.offsetWidth; t.classList.add("show");
189
+ setTimeout(()=>{ t.hidden = true; }, 2000);
190
+ }
191
+
192
+ /* تصدير/مشاركة Excel: Web Share أولاً ثم تنزيل كبديل */
193
+ async function exportExcel(){
194
+ const rows = readTable();
195
+ if(!rows.length){ toast("لا يوجد بيانات لتصديرها."); return; }
196
+
197
+ const aoa = [EXPORT_COLUMNS, ...rows.map(r=>EXPORT_COLUMNS.map(c=>r[c]||""))];
198
+ const ws = XLSX.utils.aoa_to_sheet(aoa);
199
+ ws["!rtl"] = true;
200
+ const wb = XLSX.utils.book_new();
201
+ XLSX.utils.book_append_sheet(wb, ws, "التذاكر");
202
+
203
+ const now = new Date();
204
+ const ts = now.toISOString().replace(/\D/g,'').slice(0,14);
205
+ const base = (document.getElementById("fname").value || "Ticket").trim() || "Ticket";
206
+ const filename = `${base}_${ts}.xlsx`;
207
+
208
+ const wbArray = XLSX.write(wb, { bookType: "xlsx", type: "array" });
209
+ const blob = new Blob([wbArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
210
+ const file = new File([blob], filename, { type: blob.type });
211
+
212
+ if (navigator.canShare && navigator.canShare({ files: [file] })) {
213
+ try { await navigator.share({ files: [file], title: "ملف التذاكر" }); toast("تمت المشاركة/الحفظ."); return; }
214
+ catch(e){ /* المستخدم أغلق ورقة المشاركة */ }
215
+ }
216
+ const url = URL.createObjectURL(blob);
217
+ const a = document.createElement("a"); a.href = url; a.download = filename;
218
+ document.body.appendChild(a); a.click(); a.remove();
219
+ setTimeout(()=>URL.revokeObjectURL(url), 1000);
220
+ toast("تم تنزيل الملف.");
221
+ }
222
+
223
+ /* نسخ الجدول كـTSV للصق مباشر في Excel */
224
+ async function copyToClipboardTSV(){
225
+ const rows = readTable();
226
+ if(!rows.length){ toast("لا يوجد بيانات لنسخها."); return; }
227
+ const header = EXPORT_COLUMNS.join("\t");
228
+ const body = rows.map(r=>EXPORT_COLUMNS.map(c=>(r[c]||"").replace(/\t/g," ")).join("\t")).join("\n");
229
+ const tsv = `${header}\n${body}`;
230
+ try{ await navigator.clipboard.writeText(tsv); toast("تم النسخ — الصق/ي في Excel."); }
231
+ catch(e){
232
+ const ta = document.createElement("textarea"); ta.value = tsv; document.body.appendChild(ta);
233
+ ta.select(); document.execCommand("copy"); document.body.removeChild(ta);
234
+ toast("تم النسخ — الصق/ي في Excel.");
235
+ }
236
+ }
237
+
238
+ /* المثال المطلوب (تذكرة واحدة) */
239
+ const SAMPLE = `نوع المشكلة : لا استطيع اكمال الاستمارة بسبب تعليق
240
+ وقت حدوث المشكلة: 21/8/2025
241
+ اسم صاحب المشكلة : نوف الناصر
242
+ رقم الهوية: 1234567890
243
+ رقم الجهاز: 01234
244
+ رقم الجوال: 0558174717
245
+ اسم المسح: الخبر
246
+ المنطقة: الشرقية`;
247
+
248
+ /* تنظيف كامل للبيانات (للسرعة والخصوصية) */
249
+ function wipeAll(){
250
+ try{
251
+ // لا نخزّن شيئًا؛ احتياطًا نمسح أي أثر جلسة
252
+ sessionStorage.clear();
253
+ localStorage.removeItem("rawTickets");
254
+ }catch{}
255
+ const rawEl = document.getElementById("raw");
256
+ const tbody = document.getElementById("tbody");
257
+ if(rawEl) rawEl.value = "";
258
+ if(tbody) tbody.innerHTML = "";
259
+ updateBadge(0);
260
+ setButtonsEnabled(false);
261
+ }
262
+
263
+ /* تهيئة وربط الأزرار + اختصارات */
264
+ function init(){
265
+ const parseBtn = document.getElementById("btn-parse");
266
+ const exportBtn = document.getElementById("btn-export");
267
+ const copyBtn = document.getElementById("btn-copy");
268
+ const clearBtn = document.getElementById("btn-clear");
269
+ const sampleBtn = document.getElementById("btn-sample");
270
+ const rawEl = document.getElementById("raw");
271
+
272
+ parseBtn.addEventListener("click", ()=>{
273
+ const raw = rawEl.value || SAMPLE;
274
+ const rows = parseTickets(raw);
275
+ buildTable(rows);
276
+ validateCells();
277
+ updateBadge(rows.length);
278
+ setButtonsEnabled(rows.length>0);
279
+ toast(`تم استخراج ${rows.length} ${rows.length===1 ? "تذكرة" : "تذاكر"}.`);
280
+ });
281
+
282
+ exportBtn.addEventListener("click", exportExcel);
283
+ copyBtn.addEventListener("click", copyToClipboardTSV);
284
+
285
+ clearBtn.addEventListener("click", ()=>{
286
+ wipeAll();
287
+ toast("تم مسح كل البيانات.");
288
+ });
289
+
290
+ sampleBtn.addEventListener("click", ()=>{ rawEl.value = SAMPLE; });
291
+
292
+ // عند الخروج/إغلاق الصفحة: امسح كل شيء
293
+ window.addEventListener("pagehide", wipeAll, { once:true });
294
+ window.addEventListener("beforeunload", wipeAll, { once:true });
295
+ document.addEventListener("visibilitychange", ()=>{
296
+ if(document.visibilityState === "hidden") wipeAll();
297
+ });
298
+
299
+ // اختصارات لوحة المفاتيح
300
+ document.addEventListener("keydown", (e)=>{
301
+ const ctrl = e.ctrlKey || e.metaKey;
302
+ if(ctrl && e.key === "Enter"){ e.preventDefault(); parseBtn.click(); }
303
+ else if(ctrl && e.key.toLowerCase() === "e"){ e.preventDefault(); exportBtn.click(); }
304
+ else if(ctrl && e.shiftKey && e.key.toLowerCase() === "c"){ e.preventDefault(); copyBtn.click(); }
305
+ else if(e.key === "Escape"){ e.preventDefault(); clearBtn.click(); }
306
+ });
307
+
308
+ setButtonsEnabled(false);
309
+ }
310
+ init();