stat2025 commited on
Commit
41ab682
·
verified ·
1 Parent(s): c385764

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +53 -22
app.js CHANGED
@@ -78,7 +78,7 @@ function compileFieldPatterns(){
78
  const lbls = labels.map(l => l.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')).join("|");
79
  pats[canonical] = [
80
  new RegExp(`(?:^|\\n)\\s*(?:${lbls})\\s*${LABEL_SEP}(.+)$`, "mi"),
81
- new RegExp(`(?:^|\\n)\\s*(?:${lbls})\\s*${LABEL_SEP}\\n\\س*(.+)`, "mi"),
82
  ];
83
  }
84
  return pats;
@@ -192,6 +192,7 @@ function validateCells(){
192
  document.addEventListener("input",(e)=>{
193
  if(e.target && e.target.closest && e.target.closest("#tbody")){
194
  validateCells();
 
195
  }
196
  });
197
 
@@ -217,16 +218,14 @@ async function exportExcel(){
217
  const nRows = rows.length + 1; // +1 للهيدر
218
  EXPORT_COLUMNS.forEach((colName, colIdx)=>{
219
  if(!textCols.has(colName)) return;
220
- for(let r = 1; r < nRows; r++){ // ابدأ من 1 (تجاهل الهيدر في 0)
221
  const addr = XLSX.utils.encode_cell({ c: colIdx, r });
222
  const cell = ws[addr];
223
  if(cell){
224
- cell.t = "s";
225
- cell.z = "@";
226
  if(typeof cell.v !== "string") cell.v = String(cell.v ?? "");
227
  if(typeof cell.w !== "string") cell.w = cell.v;
228
  }else{
229
- // إن كانت الخلية فارغة، أنشئ خلية نصية فارغة لضمان التنسيق
230
  ws[addr] = { t:"s", v:"", z:"@" };
231
  }
232
  }
@@ -244,12 +243,10 @@ async function exportExcel(){
244
  const blob = new Blob([wbArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
245
  const file = new File([blob], filename, { type: blob.type });
246
 
247
- // موبايل: مشاركة/حفظ من ورقة المشاركة
248
  if (navigator.canShare && navigator.canShare({ files: [file] })) {
249
  try { await navigator.share({ files: [file], title: "ملف التذاكر" }); toast("تمت المشاركة/الحفظ."); return; }
250
  catch(e){ /* المستخدم أغلق ورقة المشاركة */ }
251
  }
252
- // بديل: تنزيل عادي
253
  const url = URL.createObjectURL(blob);
254
  const a = document.createElement("a"); a.href = url; a.download = filename;
255
  document.body.appendChild(a); a.click(); a.remove();
@@ -267,13 +264,12 @@ async function copyToClipboardTSV(){
267
  const body = rows.map(r =>
268
  EXPORT_COLUMNS.map(c => {
269
  let v = (r[c] ?? "").toString().replace(/\t/g," ");
270
- // إذا العمود نصي ونظنه رقمي/قد يبدأ بصفر، أضف ' لمنع إزالة الأصفار في Excel
271
  if(textCols.has(c) && v && /^[0-9]+$/.test(v)) v = "'" + v;
272
  return v;
273
  }).join("\t")
274
  ).join("\r\n");
275
 
276
- const tsv = "\uFEFF" + header + "\r\n" + body; // BOM + CRLF
277
 
278
  try{
279
  await navigator.clipboard.writeText(tsv);
@@ -296,9 +292,39 @@ const SAMPLE = `نوع المشكلة : لا استطيع اكمال الاست
296
  اسم المسح: الخبر
297
  المنطقة: الشرقية`;
298
 
299
- /* تنظيف كامل عند المسح أو الخروج لسرعة الصفحة */
300
- function wipeAll(){
301
- try{ sessionStorage.clear(); localStorage.removeItem("rawTickets"); }catch{}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  const rawEl = document.getElementById("raw");
303
  const tbody = document.getElementById("tbody");
304
  if(rawEl) rawEl.value = "";
@@ -315,14 +341,19 @@ function init(){
315
  const clearBtn = document.getElementById("btn-clear");
316
  const sampleBtn = document.getElementById("btn-sample");
317
  const rawEl = document.getElementById("raw");
 
 
 
 
318
 
319
  parseBtn.addEventListener("click", ()=>{
320
- const raw = rawEl.value || SAMPLE;
321
  const rows = parseTickets(raw);
322
  buildTable(rows);
323
  validateCells();
324
  updateBadge(rows.length);
325
  setButtonsEnabled(rows.length>0);
 
326
  toast(`تم استخراج ${rows.length} ${rows.length===1 ? "تذكرة" : "تذاكر"}.`);
327
  });
328
 
@@ -330,18 +361,18 @@ function init(){
330
  copyBtn.addEventListener("click", copyToClipboardTSV);
331
 
332
  clearBtn.addEventListener("click", ()=>{
333
- wipeAll();
 
334
  toast("تم مسح كل البيانات.");
335
  });
336
 
337
- sampleBtn.addEventListener("click", ()=>{ rawEl.value = SAMPLE; });
338
 
339
- // عند الخروج/إغلاق الصفحة
340
- window.addEventListener("pagehide", wipeAll, { once:true });
341
- window.addEventListener("beforeunload", wipeAll, { once:true });
342
- document.addEventListener("visibilitychange", ()=>{
343
- if(document.visibilityState === "hidden") wipeAll();
344
- });
345
 
346
  // اختصارات لوحة المفاتيح
347
  document.addEventListener("keydown", (e)=>{
@@ -352,6 +383,6 @@ function init(){
352
  else if(e.key === "Escape"){ e.preventDefault(); clearBtn.click(); }
353
  });
354
 
355
- setButtonsEnabled(false);
356
  }
357
  init();
 
78
  const lbls = labels.map(l => l.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')).join("|");
79
  pats[canonical] = [
80
  new RegExp(`(?:^|\\n)\\s*(?:${lbls})\\s*${LABEL_SEP}(.+)$`, "mi"),
81
+ new RegExp(`(?:^|\\n)\\s*(?:${lbls})\\s*${LABEL_SEP}\\n\\s*(.+)`, "mi"),
82
  ];
83
  }
84
  return pats;
 
192
  document.addEventListener("input",(e)=>{
193
  if(e.target && e.target.closest && e.target.closest("#tbody")){
194
  validateCells();
195
+ saveState(); // حفظ لحظي عند تعديل الخلايا
196
  }
197
  });
198
 
 
218
  const nRows = rows.length + 1; // +1 للهيدر
219
  EXPORT_COLUMNS.forEach((colName, colIdx)=>{
220
  if(!textCols.has(colName)) return;
221
+ for(let r = 1; r < nRows; r++){
222
  const addr = XLSX.utils.encode_cell({ c: colIdx, r });
223
  const cell = ws[addr];
224
  if(cell){
225
+ cell.t = "s"; cell.z = "@";
 
226
  if(typeof cell.v !== "string") cell.v = String(cell.v ?? "");
227
  if(typeof cell.w !== "string") cell.w = cell.v;
228
  }else{
 
229
  ws[addr] = { t:"s", v:"", z:"@" };
230
  }
231
  }
 
243
  const blob = new Blob([wbArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
244
  const file = new File([blob], filename, { type: blob.type });
245
 
 
246
  if (navigator.canShare && navigator.canShare({ files: [file] })) {
247
  try { await navigator.share({ files: [file], title: "ملف التذاكر" }); toast("تمت المشاركة/الحفظ."); return; }
248
  catch(e){ /* المستخدم أغلق ورقة المشاركة */ }
249
  }
 
250
  const url = URL.createObjectURL(blob);
251
  const a = document.createElement("a"); a.href = url; a.download = filename;
252
  document.body.appendChild(a); a.click(); a.remove();
 
264
  const body = rows.map(r =>
265
  EXPORT_COLUMNS.map(c => {
266
  let v = (r[c] ?? "").toString().replace(/\t/g," ");
 
267
  if(textCols.has(c) && v && /^[0-9]+$/.test(v)) v = "'" + v;
268
  return v;
269
  }).join("\t")
270
  ).join("\r\n");
271
 
272
+ const tsv = "\uFEFF" + header + "\r\n" + body;
273
 
274
  try{
275
  await navigator.clipboard.writeText(tsv);
 
292
  اسم المسح: الخبر
293
  المنطقة: الشرقية`;
294
 
295
+ /* ================= حفظ واسترجاع الحالة ================= */
296
+ const STATE_KEY = "ticketParserState_v1";
297
+ function saveState(){
298
+ try{
299
+ const raw = document.getElementById("raw")?.value || "";
300
+ const fname = document.getElementById("fname")?.value || "Ticket";
301
+ const rows = readTable();
302
+ const state = { raw, fname, rows };
303
+ localStorage.setItem(STATE_KEY, JSON.stringify(state));
304
+ }catch{}
305
+ }
306
+ function loadState(){
307
+ try{
308
+ const s = localStorage.getItem(STATE_KEY);
309
+ if(!s) return false;
310
+ const { raw, fname, rows } = JSON.parse(s);
311
+ if(typeof raw === "string"){ const el=document.getElementById("raw"); if(el) el.value = raw; }
312
+ if(typeof fname === "string"){ const el=document.getElementById("fname"); if(el) el.value = fname; }
313
+ if(Array.isArray(rows) && rows.length){
314
+ buildTable(rows);
315
+ validateCells();
316
+ updateBadge(rows.length);
317
+ setButtonsEnabled(true);
318
+ }
319
+ return true;
320
+ }catch{ return false; }
321
+ }
322
+ function clearState(){
323
+ try{ localStorage.removeItem(STATE_KEY); }catch{}
324
+ }
325
+
326
+ /* تنظيف واجهة فقط (يُستدعى من زر مسح) */
327
+ function wipeUI(){
328
  const rawEl = document.getElementById("raw");
329
  const tbody = document.getElementById("tbody");
330
  if(rawEl) rawEl.value = "";
 
341
  const clearBtn = document.getElementById("btn-clear");
342
  const sampleBtn = document.getElementById("btn-sample");
343
  const rawEl = document.getElementById("raw");
344
+ const fnameEl = document.getElementById("fname");
345
+
346
+ // استرجاع الحالة المخزنة (لا نمسح شيئًا عند الدخول)
347
+ loadState();
348
 
349
  parseBtn.addEventListener("click", ()=>{
350
+ const raw = (rawEl.value || SAMPLE);
351
  const rows = parseTickets(raw);
352
  buildTable(rows);
353
  validateCells();
354
  updateBadge(rows.length);
355
  setButtonsEnabled(rows.length>0);
356
+ saveState(); // نحفظ فور التحليل
357
  toast(`تم استخراج ${rows.length} ${rows.length===1 ? "تذكرة" : "تذاكر"}.`);
358
  });
359
 
 
361
  copyBtn.addEventListener("click", copyToClipboardTSV);
362
 
363
  clearBtn.addEventListener("click", ()=>{
364
+ clearState(); // امسح التخزين
365
+ wipeUI(); // نظّف الواجهة
366
  toast("تم مسح كل البيانات.");
367
  });
368
 
369
+ sampleBtn.addEventListener("click", ()=>{ rawEl.value = SAMPLE; saveState(); });
370
 
371
+ rawEl.addEventListener("input", saveState);
372
+ fnameEl.addEventListener("input", saveState);
373
+
374
+ // لا نضيف أي مسح عند الخروج/الإغلاق — تلبية لطلبك
375
+ // (أزلنا pagehide / beforeunload / visibilitychange)
 
376
 
377
  // اختصارات لوحة المفاتيح
378
  document.addEventListener("keydown", (e)=>{
 
383
  else if(e.key === "Escape"){ e.preventDefault(); clearBtn.click(); }
384
  });
385
 
386
+ setButtonsEnabled(!!document.getElementById("tbody")?.children.length);
387
  }
388
  init();