diff --git a/web/src/pages/Citizens.tsx b/web/src/pages/Citizens.tsx index 353432b7..71bc3353 100644 --- a/web/src/pages/Citizens.tsx +++ b/web/src/pages/Citizens.tsx @@ -133,31 +133,45 @@ export default function Citizens() { return; } - // Validate file size (max 2MB for localStorage) - if (file.size > 2 * 1024 * 1024) { - toast({ - title: t('citizens.fileTooLarge'), - description: t('citizens.maxFileSize'), - variant: "destructive" - }); - return; - } - setUploadingPhoto(true); try { - // Convert file to base64 data URL + // Load image, resize to fit ID card photo area, compress to JPEG const dataUrl = await new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onloadend = () => { - if (reader.result) { - resolve(reader.result as string); - } else { - reject(new Error('Failed to read file')); + const img = new Image(); + img.onload = () => { + const MAX_DIM = 400; // max width or height in px + let { width, height } = img; + + // Scale down if larger than MAX_DIM + if (width > MAX_DIM || height > MAX_DIM) { + const ratio = Math.min(MAX_DIM / width, MAX_DIM / height); + width = Math.round(width * ratio); + height = Math.round(height * ratio); } + + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext('2d'); + if (!ctx) { reject(new Error('Canvas not supported')); return; } + + ctx.drawImage(img, 0, 0, width, height); + + // Compress as JPEG, start at 0.85 quality, reduce if still too large + let quality = 0.85; + let result = canvas.toDataURL('image/jpeg', quality); + + // Ensure it fits in localStorage (target < 500KB base64) + while (result.length > 500_000 && quality > 0.3) { + quality -= 0.1; + result = canvas.toDataURL('image/jpeg', quality); + } + + resolve(result); }; - reader.onerror = () => reject(new Error('FileReader error')); - reader.readAsDataURL(file); + img.onerror = () => reject(new Error('Failed to load image')); + img.src = URL.createObjectURL(file); }); // Save to localStorage with profile @@ -323,35 +337,35 @@ export default function Citizens() { {/* Title Section */} -
-

+
+

{t('citizens.portalTitle')}

-

+

{t('citizens.digitalKurdistan')}

{/* Announcements Widget - Modern Carousel */} -
+
-
+
-
+
- -

{t('citizens.announcements')}

+ +

{t('citizens.announcements')}

-

{currentAnnouncement.title}

-

{currentAnnouncement.description}

+

{currentAnnouncement.title}

+

{currentAnnouncement.description}

{currentAnnouncement.date}

{/* Modern dots indicator */} @@ -374,52 +388,15 @@ export default function Citizens() { onClick={nextAnnouncement} className="z-10 text-white/80 hover:text-white transition-all hover:scale-110" > - +
- {/* Main Entrance Cards - Grid with exactly 2 cards */} -
- {/* LEFT: Citizens Issues */} - - -
-
- -
-
-

- {t('citizens.citizenIssues')} -

-
-
- - {/* RIGHT: Gov Entrance */} - - -
-
- -
-
-

- {t('citizens.govEntrance')} -

-
-
-
- {/* Digital Citizen ID Card - Pure HTML/CSS Design */} -
+
+ {/* Main Entrance Cards - Compact 2-column buttons */} +
+ {/* LEFT: Citizens Issues */} + + +
+
+ +
+
+

+ {t('citizens.citizenIssues')} +

+
+
+ + {/* RIGHT: Gov Entrance */} + + +
+
+ +
+
+

+ {t('citizens.govEntrance')} +

+
+
+
+ {/* Government Entrance - Citizen Number Verification Dialog */}