import { useEffect, useState, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; import { usePezkuwi } from '@/contexts/PezkuwiContext'; import { useDashboard } from '@/contexts/DashboardContext'; import { FileText, Building2, Home, Bell, ChevronLeft, ChevronRight, Upload, User, Sun, ShieldCheck, Pencil } from 'lucide-react'; import { useToast } from '@/hooks/use-toast'; import { getUserRoleCategories } from '@pezkuwi/lib/tiki'; // LocalStorage key prefix for citizen profile data const CITIZEN_PROFILE_KEY = 'citizen_profile_'; interface CitizenProfileData { fullName: string; fatherName: string; location: string; photoUrl: string | null; } // Mock announcements data const announcements = [ { id: 1, title: "Bijî Azadiya Kurdistanê! (Long Live Free Kurdistan!)", description: "Bi serkeftina sîstema me ya dijîtal, em gaveke din li pêşiya azadiya xwe datînin. (With the success of our digital system, we take another step towards our freedom.)", date: "2025-01-19" }, { id: 2, title: "Daxuyaniya Nû ya Hikûmetê (New Government Announcement)", description: "Pergalên nû yên xizmetguzariya dijîtal ji bo hemû welatiyan aktîv bûn. (New digital service systems have been activated for all citizens.)", date: "2025-01-18" }, { id: 3, title: "Civîna Giştî ya Welatiyên (Citizens General Assembly)", description: "Civîna mehane ya welatiyên di 25ê vê mehê de pêk tê. Beşdarî bibin! (Monthly citizens assembly takes place on the 25th of this month. Participate!)", date: "2025-01-17" } ]; export default function Citizens() { const { selectedAccount } = usePezkuwi(); const navigate = useNavigate(); const { toast } = useToast(); const { t } = useTranslation(); const { nftDetails, citizenNumber, loading } = useDashboard(); const [currentAnnouncementIndex, setCurrentAnnouncementIndex] = useState(0); const [uploadingPhoto, setUploadingPhoto] = useState(false); const fileInputRef = useRef(null); const [showGovDialog, setShowGovDialog] = useState(false); const [showCitizensDialog, setShowCitizensDialog] = useState(false); const [citizenNumberInput, setCitizenNumberInput] = useState(''); const [isVerifying, setIsVerifying] = useState(false); const [dialogType, setDialogType] = useState<'gov' | 'citizens'>('gov'); // Citizen profile from localStorage const [citizenProfile, setCitizenProfile] = useState({ fullName: '', fatherName: '', location: '', photoUrl: null }); const [showEditModal, setShowEditModal] = useState(false); const [editForm, setEditForm] = useState({ fullName: '', fatherName: '', location: '', photoUrl: null }); // Load citizen profile from localStorage on mount useEffect(() => { if (selectedAccount?.address) { const storageKey = CITIZEN_PROFILE_KEY + selectedAccount.address; const savedProfile = localStorage.getItem(storageKey); if (savedProfile) { try { const parsed = JSON.parse(savedProfile) as CitizenProfileData; setCitizenProfile(parsed); setEditForm(parsed); } catch (e) { console.error('Error parsing saved profile:', e); } } else { // No saved profile - prompt user to fill in their info setShowEditModal(true); } } }, [selectedAccount?.address]); // Save citizen profile to localStorage const saveCitizenProfile = (data: CitizenProfileData) => { if (selectedAccount?.address) { const storageKey = CITIZEN_PROFILE_KEY + selectedAccount.address; localStorage.setItem(storageKey, JSON.stringify(data)); setCitizenProfile(data); toast({ title: t('citizens.profileSaved'), description: t('citizens.profileSavedDesc') }); } }; const handlePhotoUpload = async (event: React.ChangeEvent) => { if (!event.target.files || !event.target.files[0]) { return; } if (!selectedAccount?.address) { toast({ title: t('citizens.walletNotConnected'), description: t('citizens.connectWallet'), variant: "destructive" }); return; } const file = event.target.files[0]; // Validate file type if (!file.type.startsWith('image/')) { toast({ title: t('citizens.fileError'), description: t('citizens.uploadImageOnly'), variant: "destructive" }); return; } setUploadingPhoto(true); try { // Load image, resize to fit ID card photo area, compress to JPEG const dataUrl = await new Promise((resolve, reject) => { 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); }; img.onerror = () => reject(new Error('Failed to load image')); img.src = URL.createObjectURL(file); }); // Save to localStorage with profile const updatedProfile = { ...citizenProfile, photoUrl: dataUrl }; saveCitizenProfile(updatedProfile); toast({ title: t('citizens.photoUploaded'), description: t('citizens.photoUploadedDesc') }); } catch (error) { console.error('Photo upload error:', error); toast({ title: t('citizens.uploadError'), description: error instanceof Error ? error.message : t('citizens.couldNotUpload'), variant: "destructive" }); } finally { setUploadingPhoto(false); } }; // Handle case where no wallet is connected if (!selectedAccount && !loading) { return (

{t('citizens.connectWalletMsg')}

); } const handleCitizensIssue = () => { // Check if user has Tiki NFT if (!nftDetails.citizenNFT) { toast({ title: t('citizens.noAccess'), description: t('citizens.noAccessDesc'), variant: "destructive" }); return; } // Show citizen number verification dialog for Citizens Issues setDialogType('citizens'); setShowCitizensDialog(true); }; const handleGovEntrance = () => { // Check if user has Tiki NFT if (!nftDetails.citizenNFT) { toast({ title: t('citizens.noAccess'), description: t('citizens.noAccessDesc'), variant: "destructive" }); return; } // Navigate directly - GovernmentEntrance will handle verification navigate('/citizens/government'); }; const handleVerifyCitizenNumber = () => { setIsVerifying(true); // Construct the full citizen number format: #42-0-123456 const actualCitizenNumber = nftDetails.citizenNFT ? `#${nftDetails.citizenNFT.collectionId}-${nftDetails.citizenNFT.itemId}-${citizenNumber}` : ''; // Clean and compare const inputCleaned = citizenNumberInput.trim().toUpperCase(); if (inputCleaned === actualCitizenNumber.toUpperCase()) { setShowGovDialog(false); setShowCitizensDialog(false); setCitizenNumberInput(''); if (dialogType === 'gov') { toast({ title: t('citizens.authSuccess'), description: t('citizens.govAuthDesc'), }); navigate('/citizens/government'); } else { toast({ title: t('citizens.authSuccess'), description: t('citizens.citizenAuthDesc'), }); navigate('/citizens/issues'); } } else { toast({ title: t('citizens.wrongNumber'), description: t('citizens.wrongNumberDesc'), variant: "destructive" }); } setIsVerifying(false); }; const nextAnnouncement = () => { setCurrentAnnouncementIndex((prev) => (prev + 1) % announcements.length); }; const prevAnnouncement = () => { setCurrentAnnouncementIndex((prev) => (prev - 1 + announcements.length) % announcements.length); }; if (loading) { return (

{t('citizens.loading')}

); } // Get role categories for display const roleCategories = getUserRoleCategories(nftDetails.roleNFTs) || { government: [], citizen: [], business: [], judicial: [] }; if (import.meta.env.DEV) console.log('Role categories:', roleCategories); const currentAnnouncement = announcements[currentAnnouncementIndex]; return (
{/* Back Button */}
{/* Title Section */}

{t('citizens.portalTitle')}

{t('citizens.digitalKurdistan')}

{/* Announcements Widget - Modern Carousel */}

{t('citizens.announcements')}

{currentAnnouncement.title}

{currentAnnouncement.description}

{currentAnnouncement.date}

{/* Modern dots indicator */}
{announcements.map((_, idx) => (
{/* Digital Citizen ID Card - Flow Layout */}
{/* Security Pattern Overlay */}
{/* Top Header Band */}
KOMARÎ KURDISTAN
REPUBLIC OF KURDISTAN
NASNAMEYA DÎJÎTAL
DIGITAL IDENTITY CARD
{/* Main Content Area - Flow layout */}
{/* Left Section - Photo */}
{citizenProfile.photoUrl ? ( Citizen Photo ) : (
)}
{/* Upload Overlay */}
{/* Middle + Right Section */}
{/* Edit Button */}
{/* Personal Info */}
{t('citizens.nameLabel')}
{citizenProfile.fullName || '...'}
{t('citizens.fatherNameLabel')}
{citizenProfile.fatherName || '...'}
{t('citizens.locationLabel')}
{citizenProfile.location || '...'}
{/* NFT & Citizen Number Badges */}
NFT ID
{nftDetails.citizenNFT ? `#${nftDetails.citizenNFT.collectionId}-${nftDetails.citizenNFT.itemId}` : 'N/A'}
Citizen No
{nftDetails.citizenNFT ? `#${nftDetails.citizenNFT.collectionId}-${nftDetails.citizenNFT.itemId}-${citizenNumber}` : 'N/A'}
VERIFIED
{/* Bottom Footer Band */}
Blockchain: Pezkuwichain People
BIJÎ KURDISTAN
Type: Welati NFT
{/* 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 */}
{t('citizens.govDialogTitle')}
{t('citizens.enterCitizenNumber')}
setCitizenNumberInput(e.target.value)} className="text-center font-mono text-lg border-2 border-green-400" onKeyDown={(e) => { if (e.key === 'Enter' && !isVerifying) { handleVerifyCitizenNumber(); } }} />
{/* Citizens Issues - Citizen Number Verification Dialog */}
{t('citizens.citizenDialogTitle')}
{t('citizens.enterCitizenNumber')}
setCitizenNumberInput(e.target.value)} className="text-center font-mono text-lg border-2 border-purple-400" onKeyDown={(e) => { if (e.key === 'Enter' && !isVerifying) { handleVerifyCitizenNumber(); } }} />
{/* Edit Profile Modal */} {t('citizens.editProfile')}
setEditForm({ ...editForm, fullName: e.target.value })} className="border-2" />
setEditForm({ ...editForm, fatherName: e.target.value })} className="border-2" />
setEditForm({ ...editForm, location: e.target.value })} className="border-2" />
); }