Skip to content

Commit 822f37e

Browse files
Update title and improve image handling in index.html
Updated the title and adjusted image sizes in the product grid and table. Enhanced image handling and removed unnecessary image compression logic.
1 parent 620627c commit 822f37e

1 file changed

Lines changed: 93 additions & 70 deletions

File tree

index.html

Lines changed: 93 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6-
<title>فَوْتَرَة كامل - نظام الفوترة الجزائري (حفظ الصور)</title>
6+
<title>فَوْتَرَة كامل - نظام الفوترة الجزائري (صور واضحة)</title>
77
<script src="https://cdn.tailwindcss.com"></script>
88
<link rel="preconnect" href="https://fonts.googleapis.com">
99
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -104,7 +104,15 @@
104104
}
105105
.dark .product-grid-card { background: #1e293b; border-color: #334155; }
106106
.product-grid-card:hover { transform: translateY(-4px); border-color: #0ea5e9; box-shadow: 0 8px 25px rgba(14,165,233,0.15); }
107-
.product-grid-card img { width: 60px; height: 60px; object-fit: cover; border-radius: 10px; border: 1px solid #e2e8f0; background: white; }
107+
/* حجم الصورة في شبكة POS - 64x64 */
108+
.product-grid-card img {
109+
width: 64px;
110+
height: 64px;
111+
object-fit: cover;
112+
border-radius: 12px;
113+
border: 1px solid #e2e8f0;
114+
background: white;
115+
}
108116
.dark .product-grid-card img { border-color: #475569; background: #0f172a; }
109117
.product-grid-card .product-name {
110118
font-weight: 800;
@@ -113,9 +121,7 @@
113121
line-height: 1.3;
114122
color: #000000;
115123
}
116-
.dark .product-grid-card .product-name {
117-
color: #f1f5f9;
118-
}
124+
.dark .product-grid-card .product-name { color: #f1f5f9; }
119125
.product-grid-card .product-price {
120126
color: #0ea5e9;
121127
font-weight: 800;
@@ -369,6 +375,37 @@
369375
margin-right: 8px;
370376
}
371377
.dark .edit-badge { background: #d97706; }
378+
379+
/* تنسيق الصورة في جدول المنتجات بحجم أكبر */
380+
.product-table-img {
381+
width: 80px;
382+
height: 80px;
383+
object-fit: cover;
384+
border-radius: 12px;
385+
border: 1px solid #e2e8f0;
386+
background: white;
387+
}
388+
.dark .product-table-img {
389+
border-color: #475569;
390+
background: #0f172a;
391+
}
392+
.product-table-img-placeholder {
393+
width: 80px;
394+
height: 80px;
395+
border-radius: 12px;
396+
background: #f1f5f9;
397+
display: flex;
398+
align-items: center;
399+
justify-content: center;
400+
color: #94a3b8;
401+
font-size: 28px;
402+
border: 1px solid #e2e8f0;
403+
}
404+
.dark .product-table-img-placeholder {
405+
background: #1e293b;
406+
border-color: #334155;
407+
color: #64748b;
408+
}
372409
</style>
373410
</head>
374411
<body class="bg-[#f7f8fb] dark:bg-slate-950 text-slate-800 dark:text-slate-100 transition-colors">
@@ -384,7 +421,7 @@
384421
</div>
385422
<div>
386423
<h1 class="font-extrabold text-lg leading-none">فَوْتَرَة</h1>
387-
<p class="text-[11px] text-slate-500 dark:text-slate-400">الإصدار الجزائري v4.5</p>
424+
<p class="text-[11px] text-slate-500 dark:text-slate-400">الإصدار الجزائري v4.6</p>
388425
</div>
389426
</div>
390427
<nav class="p-3 space-y-1.5 overflow-y-auto">
@@ -555,15 +592,15 @@ <h2 class="text-xl font-extrabold">إدارة الفواتير</h2>
555592
</div>
556593
</section>
557594

558-
<!-- PRODUCTS -->
595+
<!-- PRODUCTS (مع صور أكبر) -->
559596
<section id="page-products" class="page hidden space-y-4 animate-in">
560597
<div class="flex items-center justify-between">
561598
<h2 class="text-xl font-extrabold">المنتجات والمخزون</h2>
562599
<button id="btn-add-product" class="h-10 px-4 rounded-xl bg-sky-600 text-white text-sm font-bold"><i class="fa-solid fa-plus ml-1"></i> منتج جديد</button>
563600
</div>
564601
<div class="bg-white dark:bg-slate-900 rounded-3xl border border-slate-200 dark:border-slate-800 overflow-hidden">
565602
<div class="overflow-x-auto table-wrap">
566-
<table class="w-full text-sm min-w-[800px]">
603+
<table class="w-full text-sm min-w-[850px]">
567604
<thead class="bg-slate-50 dark:bg-slate-800/50"><tr class="text-right text-slate-500">
568605
<th class="p-3">الصورة</th><th class="p-3">المنتج</th><th class="p-3">المرجع</th><th class="p-3">سعر الشراء</th><th class="p-3">سعر البيع HT</th><th class="p-3">TVA %</th><th class="p-3">المخزون</th><th class="p-3">إجراءات</th>
569606
</tr></thead>
@@ -1237,16 +1274,36 @@ <h3 id="modal-title" class="font-extrabold text-lg">إضافة</h3>
12371274
}
12381275

12391276
// ============================================================
1240-
// PRODUCTS (مع تحسين حفظ الصورة)
1277+
// PRODUCTS (مع صور أكبر)
12411278
// ============================================================
12421279
let pendingAddToInvoice = false;
12431280

1281+
// دالة معالجة الصورة
1282+
function handleImageFile(file) {
1283+
return new Promise((resolve) => {
1284+
const reader = new FileReader();
1285+
reader.onload = function(e) {
1286+
const dataUrl = e.target.result;
1287+
if (dataUrl.length > 2 * 1024 * 1024) {
1288+
showToast('⚠️ الصورة كبيرة جداً، قد تواجه مشكلة في الأداء', 'warning', 4000);
1289+
}
1290+
resolve(dataUrl);
1291+
};
1292+
reader.onerror = function() {
1293+
showToast('فشل قراءة الصورة', 'error');
1294+
resolve('');
1295+
};
1296+
reader.readAsDataURL(file);
1297+
});
1298+
}
1299+
12441300
function renderProducts() {
12451301
$('#products-table').innerHTML = state.products.map(p => `
12461302
<tr class="border-b dark:border-slate-800 hover:bg-slate-50 dark:hover:bg-slate-800/50">
12471303
<td class="p-3">
1248-
${p.image ? `<img src="${p.image}" class="w-12 h-12 rounded-lg object-cover border border-slate-200 dark:border-slate-700" alt="${p.name}">` :
1249-
`<div class="w-12 h-12 rounded-lg bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-400"><i class="fa-solid fa-image"></i></div>`}
1304+
${p.image && p.image.startsWith('data:image') ?
1305+
`<img src="${p.image}" class="product-table-img" alt="${p.name}">` :
1306+
`<div class="product-table-img-placeholder"><i class="fa-solid fa-image"></i></div>`}
12501307
</td>
12511308
<td class="p-3 font-bold">${p.name}</td>
12521309
<td class="p-3 font-mono text-xs">${p.ref}</td>
@@ -1270,8 +1327,9 @@ <h3 id="modal-title" class="font-extrabold text-lg">إضافة</h3>
12701327
$('#product-grid').innerHTML = list.map(p => `
12711328
<div class="product-grid-card" onclick="addItemById(${p.id})">
12721329
<button class="add-btn" onclick="event.stopPropagation(); addItemById(${p.id})" aria-label="إضافة المنتج">+</button>
1273-
${p.image ? `<img src="${p.image}" alt="${p.name}">` :
1274-
`<div class="w-[60px] h-[60px] rounded-xl bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-400"><i class="fa-solid fa-image text-2xl"></i></div>`}
1330+
${p.image && p.image.startsWith('data:image') ?
1331+
`<img src="${p.image}" alt="${p.name}">` :
1332+
`<div class="w-16 h-16 rounded-xl bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-400"><i class="fa-solid fa-image text-2xl"></i></div>`}
12751333
<div class="product-name">${p.name}</div>
12761334
<div class="product-price">${money(p.price)}</div>
12771335
<div class="text-xs text-slate-500">${p.ref}</div>
@@ -1281,32 +1339,6 @@ <h3 id="modal-title" class="font-extrabold text-lg">إضافة</h3>
12811339

12821340
$('#btn-add-product').onclick = () => openProduct();
12831341

1284-
// دالة لضغط الصورة إذا كانت كبيرة
1285-
function compressImage(dataUrl, maxWidth = 200, maxHeight = 200, quality = 0.7) {
1286-
return new Promise((resolve) => {
1287-
const img = new Image();
1288-
img.onload = function() {
1289-
let width = img.width;
1290-
let height = img.height;
1291-
if (width > maxWidth) {
1292-
height = (maxWidth / width) * height;
1293-
width = maxWidth;
1294-
}
1295-
if (height > maxHeight) {
1296-
width = (maxHeight / height) * width;
1297-
height = maxHeight;
1298-
}
1299-
const canvas = document.createElement('canvas');
1300-
canvas.width = width;
1301-
canvas.height = height;
1302-
const ctx = canvas.getContext('2d');
1303-
ctx.drawImage(img, 0, 0, width, height);
1304-
resolve(canvas.toDataURL('image/jpeg', quality));
1305-
};
1306-
img.src = dataUrl;
1307-
});
1308-
}
1309-
13101342
function openProduct(p = null, ref = '', addToInvoice = false) {
13111343
pendingAddToInvoice = addToInvoice;
13121344
$('#modal-title').textContent = p ? 'تعديل منتج' : (ref ? 'إضافة منتج جديد من المسح' : 'منتج جديد');
@@ -1340,29 +1372,16 @@ <h3 id="modal-title" class="font-extrabold text-lg">إضافة</h3>
13401372
fileInput.addEventListener('change', async function(e) {
13411373
const file = e.target.files[0];
13421374
if (file) {
1343-
// التحقق من حجم الصورة
1344-
if (file.size > 1024 * 1024) { // أكبر من 1 ميجابايت
1345-
showToast('الصورة كبيرة جداً، سيتم ضغطها تلقائياً', 'warning', 3000);
1346-
}
1347-
const reader = new FileReader();
1348-
reader.onload = async function(ev) {
1349-
let dataUrl = ev.target.result;
1350-
// ضغط الصورة إذا كانت كبيرة
1351-
if (dataUrl.length > 500 * 1024) { // أكبر من 500 كيلوبايت
1352-
try {
1353-
dataUrl = await compressImage(dataUrl, 300, 300, 0.7);
1354-
} catch(err) {
1355-
console.warn('فشل ضغط الصورة', err);
1356-
}
1357-
}
1375+
try {
1376+
const dataUrl = await handleImageFile(file);
13581377
previewImg.src = dataUrl;
13591378
preview.classList.remove('hidden');
1360-
// تخزين البيانات مؤقتاً في input hidden
13611379
fileInput.dataset.imageData = dataUrl;
1362-
};
1363-
reader.readAsDataURL(file);
1380+
} catch(err) {
1381+
console.error('خطأ في تحميل الصورة:', err);
1382+
showToast('فشل تحميل الصورة', 'error');
1383+
}
13641384
} else {
1365-
// إذا لم يتم اختيار ملف، نستخدم الصورة القديمة
13661385
if (imageSrc) {
13671386
previewImg.src = imageSrc;
13681387
preview.classList.remove('hidden');
@@ -1376,19 +1395,23 @@ <h3 id="modal-title" class="font-extrabold text-lg">إضافة</h3>
13761395
}
13771396

13781397
function saveProduct(id) {
1379-
const name = $('#p-name').value.trim();
1380-
if (!name) return showToast('ادخل الاسم', 'error');
1381-
const fileInput = document.getElementById('p-image');
1382-
let imageData = '';
1383-
// إذا كان هناك صورة جديدة تم تحميلها، نأخذها من dataset
1384-
if (fileInput && fileInput.dataset.imageData) {
1385-
imageData = fileInput.dataset.imageData;
1386-
} else {
1387-
// وإلا نستخدم الصورة القديمة من المنتج إن وجدت
1388-
const existing = state.products.find(p => p.id === id);
1389-
imageData = existing ? existing.image || '' : '';
1398+
try {
1399+
const name = $('#p-name').value.trim();
1400+
if (!name) return showToast('ادخل الاسم', 'error');
1401+
1402+
const fileInput = document.getElementById('p-image');
1403+
let imageData = '';
1404+
if (fileInput && fileInput.dataset && fileInput.dataset.imageData) {
1405+
imageData = fileInput.dataset.imageData;
1406+
} else {
1407+
const existing = state.products.find(p => p.id === id);
1408+
imageData = existing ? existing.image || '' : '';
1409+
}
1410+
actuallySaveProduct(id, name, imageData);
1411+
} catch(err) {
1412+
console.error('خطأ في حفظ المنتج:', err);
1413+
showToast('حدث خطأ أثناء حفظ المنتج', 'error');
13901414
}
1391-
actuallySaveProduct(id, name, imageData);
13921415
}
13931416

13941417
function actuallySaveProduct(id, name, imageData) {

0 commit comments

Comments
 (0)