39038-vm/includes/app.php
2026-03-24 05:58:53 +00:00

920 lines
40 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../db/config.php';
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$lang = $_GET['lang'] ?? ($_SESSION['lang'] ?? 'ar');
$lang = $lang === 'en' ? 'en' : 'ar';
$_SESSION['lang'] = $lang;
$dir = $lang === 'ar' ? 'rtl' : 'ltr';
$translations = [
"en" => array (
'app_name' => 'CargoLink',
'nav_home' => 'Overview',
'nav_login' => 'Login',
'nav_shipper' => 'Shipper Desk',
'nav_owner' => 'Truck Owner Desk',
'nav_admin' => 'Admin Panel',
'nav_theme' => 'Theme',
'nav_get_started' => 'Get Started',
'hero_title' => 'Move cargo faster with verified trucks.',
'hero_subtitle' => 'Post shipments, collect offers, and pay via Thawani or bank transfer. Built for local and nearby cross-border moves.',
'hero_tagline' => 'Multilingual Logistics Marketplace',
'register_shipper' => 'Register as Shipper',
'register_owner' => 'Register as Truck Owner',
'cta_shipper' => 'Post a shipment',
'cta_owner' => 'Find loads',
'cta_admin' => 'Open admin',
'stats_shipments' => 'Shipments posted',
'stats_offers' => 'Active offers',
'stats_confirmed' => 'Confirmed trips',
'section_workflow' => 'How it works',
'recent_shipments' => 'Recent shipments',
'step_post' => 'Shipper posts cargo details and preferred payment.',
'step_offer' => 'Truck owners respond with their best rate.',
'step_confirm' => 'Admin confirms booking and status.',
'step_confirm_desc' => 'Secure booking and track the delivery until completion.',
'shipper_dashboard' => 'Shipper Dashboard',
'new_shipment' => 'Create shipment',
'shipper_name' => 'Shipper name',
'shipper_company' => 'Company',
'origin' => 'Origin city',
'destination' => 'Destination city',
'cargo' => 'Cargo description',
'cargo_placeholder' => 'e.g. 20 Pallets of Electronics',
'weight' => 'Weight (tons)',
'pickup_date' => 'Pickup date',
'delivery_date' => 'Delivery date',
'payment_method' => 'Payment method',
'payment_thawani' => 'Thawani online payment',
'payment_bank' => 'Bank transfer',
'submit_shipment' => 'Submit shipment',
'shipments_list' => 'Your latest shipments',
'status' => 'Status',
'offer' => 'Best offer',
'actions' => 'Actions',
'view' => 'View',
'owner_dashboard' => 'Truck Owner Dashboard',
'available_shipments' => 'Available shipments',
'offer_price' => 'Offer price',
'offer_owner' => 'Truck owner name',
'submit_offer' => 'Send offer',
'admin_dashboard' => 'Admin Dashboard',
'update_status' => 'Update status',
'save' => 'Save',
'shipment_detail' => 'Shipment detail',
'created_at' => 'Created',
'best_offer' => 'Best offer',
'assign_owner' => 'Assigned owner',
'no_shipments' => 'No shipments yet. Create the first one to get started.',
'no_offers' => 'No offers yet.',
'success_shipment' => 'Shipment posted successfully.',
'success_offer' => 'Offer submitted to the shipper.',
'success_status' => 'Status updated.',
'error_required' => 'Please fill in all required fields.',
'error_invalid' => 'Please enter valid values.',
'status_posted' => 'Posted',
'status_offered' => 'Offered',
'status_confirmed' => 'Confirmed',
'status_in_transit' => 'In transit',
'status_delivered' => 'Delivered',
'footer_note' => 'This is the initial MVP slice. Payments are not yet connected.',
'marketing_title_1' => 'For Shippers',
'marketing_desc_1' => 'Find the right truck for your cargo quickly and securely. Post your load and get offers instantly.',
'marketing_title_2' => 'For Truck Owners',
'marketing_desc_2' => 'Maximize your earnings and eliminate empty miles. Browse available shipments and offer your rate.',
'motivation_phrase' => 'Empowering the logistics of tomorrow.',
'why_choose_us' => 'Why Choose CargoLink?',
'feature_1_title' => 'Fast Matching',
'feature_1_desc' => 'Connect with available trucks or shipments in minutes.',
'feature_2_title' => 'Secure Payments',
'feature_2_desc' => 'Your transactions are protected with security.',
'feature_3_title' => 'Verified Users',
'feature_3_desc' => 'We verify all truck owners to ensure peace of mind.',
'view_faq' => 'View FAQ',
'faq_title' => 'Have Questions?',
'faq_subtitle' => 'Check out our Frequently Asked Questions to learn more about how our platform works.',
'motivation_title' => 'Ready to transform your logistics?',
'motivation_subtitle' => 'Join our platform today to find reliable trucks or secure the best shipments in the market.',
'company' => 'Company',
'about_us' => 'About Us',
'careers' => 'Careers',
'contact' => 'Contact',
'resources' => 'Resources',
'help_center' => 'Help Center / FAQ',
'terms_of_service' => 'Terms of Service',
'privacy_policy' => 'Privacy Policy',
'language' => 'Language',
'all_rights_reserved' => 'All rights reserved.',
'dashboard' => 'Dashboard',
'shipments' => 'Shipments',
'reports' => 'Reports',
'summary_report' => 'Summary Report',
'shipments_by_origin_country' => 'Shipments by Origin Country',
'shipments_by_dest_country' => 'Shipments by Destination Country',
'shipments_by_origin_city' => 'Shipments by Origin City',
'shipments_by_dest_city' => 'Shipments by Destination City',
'shipments_by_shipper' => 'Shipments by Shipper',
'generated' => 'Generated',
'report_type' => 'Report Type',
'period' => 'Period',
'analyze_performance' => 'Analyze platform performance and metrics.',
'print' => 'Print',
'start_date' => 'Start Date',
'end_date' => 'End Date',
'apply_filter' => 'Apply Filter',
'no_paid_shipments' => 'No paid shipments found for this period.',
'name' => 'Name',
'total_amount' => 'Total Amount',
'profit' => 'Profit',
'total_label' => 'Total',
'printed_by' => 'Printed By',
'analytics' => 'Analytics',
'shipper_shipments' => 'Shipper Shipments',
'truck_owners_statements' => 'Truck Owners Statements',
'nav_platform_users' => 'Platform Users',
'settings' => 'Settings',
'company_setting' => 'Company Setting',
'integrations' => 'Integrations',
'notification_templates' => 'Notification Templates',
'locations' => 'Locations',
'countries' => 'Countries',
'cities' => 'Cities',
'users' => 'Users',
'shippers' => 'Shippers',
'truck_owners' => 'Truck Owners',
'trucks' => 'Trucks',
'view_truck_docs_in_edit' => 'View truck documents in the Edit page.',
'user_registration' => 'User Registration',
'pages' => 'Pages',
'faqs' => 'FAQs',
'landing_pages' => 'Landing Pages',
'edit_homepage' => 'Edit homepage content and sections',
'view_details' => 'View Details',
'manage_shippers' => 'Manage Shippers',
'manage_registered_shippers' => 'Manage registered shippers.',
'search_placeholder_shipper' => 'Search name, email, company...',
'all_statuses' => 'All Statuses',
'pending' => 'Pending',
'rejected' => 'Rejected',
'active' => 'Active',
'no_shippers_criteria' => 'No shippers found matching your criteria.',
'no_shippers_registered' => 'No shippers registered yet.',
'name_company' => 'Name / Company',
'location' => 'Location',
'edit_shipper' => 'Edit Shipper',
'approve' => 'Approve',
'reject' => 'Reject',
'delete' => 'Delete',
'delete_confirm_shipper' => 'Delete this shipper forever?',
'loading' => 'Loading...',
'manage_truck_owners' => 'Manage Truck Owners',
'review_registrations' => 'Review registrations and approve truck owners.',
'search_placeholder_owner' => 'Search name, email, plate...',
'no_owners_criteria' => 'No truck owners found matching your criteria.',
'no_owners_registered' => 'No truck owners registered yet.',
'name_email' => 'Name / Email',
'truck_info' => 'Truck Info',
'documents' => 'Documents',
'view_docs' => 'View Docs',
'edit_owner' => 'Edit Owner',
'delete_confirm_owner' => 'Delete this truck owner forever?',
'docs_for' => 'Documents for',
'truck_reg' => 'Truck Registration',
'no_picture' => 'No picture uploaded.',
'cap' => 'Cap',
'manage_shipments' => 'Manage Shipments',
'shipments_header' => 'Shipments',
'shipments_subtitle' => 'Manage all shipments across the platform.',
'flash_shipment_deleted' => 'Shipment deleted successfully.',
'search_shipments_placeholder' => 'Search shipments...',
'search_label' => 'Search',
'sort_by' => 'Sort By',
'sort_newest' => 'Newest First',
'sort_oldest' => 'Oldest First',
'sort_pickup_soonest' => 'Pickup Date (Soonest)',
'sort_pickup_latest' => 'Pickup Date (Latest)',
'no_shipments_found_criteria' => 'No shipments found matching your criteria.',
'no_shipments_platform' => 'No shipments found on the platform yet.',
'id_col' => 'ID',
'dates_col' => 'Dates',
'from_label' => 'From:',
'to_label' => 'To:',
'pick_label' => 'Pick:',
'drop_label' => 'Drop:',
'view_shipment' => 'View Shipment',
'edit_shipment_tooltip' => 'Edit Shipment',
'confirm_delete_shipment' => 'Delete this shipment?',
'showing' => 'Showing',
'of' => 'of',
'previous' => 'Previous',
'next' => 'Next',
'error_occurred' => 'An error occurred',
'failed_load_form' => 'Failed to load form.',
'edit_shipment_title' => 'Edit Shipment #',
'update_shipment_details' => 'Update shipment details and status.',
'shipment_not_found' => 'Shipment not found',
'shipment_updated_success' => 'Shipment updated successfully.',
'invalid_id' => 'Invalid ID',
'back' => 'Back',
'shipment_details' => 'Shipment Details',
'origin_country' => 'Origin Country',
'destination_country' => 'Destination Country',
'select_country_placeholder' => 'Select Country',
'select_city_placeholder' => 'Select City',
'loading_cities' => 'Loading...',
'error_loading_cities' => 'Error loading cities',
'cancel' => 'Cancel',
'my_profile' => 'My Profile',
'profile_picture' => 'Profile Picture',
'change_picture' => 'Change Picture',
'picture_hint' => 'Click the camera icon to update.',
'full_name' => 'Full Name',
'email_address' => 'Email Address',
'email_hint' => 'Email cannot be changed.',
'account_role' => 'Account Role',
'change_password' => 'Change Password',
'new_password' => 'New Password',
'confirm_password' => 'Confirm Password',
'save_changes' => 'Save Changes',
'passwords_do_not_match' => 'Passwords do not match.',
'password_too_short' => 'Password must be at least 6 characters.',
'profile_updated' => 'Profile updated successfully.',
'password_updated' => 'Password updated successfully.',
'upload_failed' => 'File upload failed.',
'invalid_image' => 'Invalid image format. Allowed: JPG, PNG, GIF, WEBP.',
'login_title' => 'Login',
'login_subtitle' => 'Access your account',
'forgot_password' => 'Forgot Password?',
'email_placeholder' => 'name@example.com',
'password_placeholder' => 'Enter your password',
'sign_in' => 'Sign In',
'dont_have_account' => 'Don\'t have an account?',
'register_now' => 'Register Now',
'reset_password_title' => 'Reset Password',
'reset_password_subtitle' => 'Enter your email to receive a reset link',
'send_reset_link' => 'Send Reset Link',
'back_to_login' => 'Back to Login',
'timezone' => 'Timezone',
'whatsapp_settings' => 'WhatsApp Settings',
'enable_whatsapp' => 'Enable WhatsApp Notifications',
'wablas_domain' => 'Wablas Domain',
'wablas_api_token' => 'Wablas API Token',
'reg_title' => 'Registration',
'reg_subtitle' => 'Create an account to get started',
'reg_success_pending' => 'Registration successful. Your account is pending approval.',
'reg_success' => 'Registration successful. You can now login.',
'role' => 'Role',
'shipper' => 'Shipper',
'truck_owner' => 'Truck Owner',
'email' => 'Email',
'password' => 'Password',
'phone' => 'Phone Number',
'country' => 'Country',
'select_country' => 'Select Country',
'city' => 'City',
'select_city' => 'Select City',
'address' => 'Address',
'shipper_details' => 'Shipper Details',
'company_name' => 'Company Name',
'truck_details' => 'Truck Details',
'truck_type' => 'Truck Type',
'load_capacity' => 'Load Capacity (Tons)',
'plate_no' => 'Plate Number',
'bank_account' => 'Bank Account Number',
'bank_name' => 'Bank Name',
'bank_branch' => 'Branch Name',
'id_card_front' => 'ID Card (Front)',
'id_card_back' => 'ID Card (Back)',
'truck_reg_front' => 'Truck Registration (Front)',
'truck_reg_back' => 'Truck Registration (Back)',
'truck_picture' => 'Truck Picture',
'create_account' => 'Create Account',
'back_to_admin' => 'Back to Admin',
'back_to_home' => 'Back to Home',
'total_revenue' => 'Total Revenue',
'shipments_analytics' => 'Shipments Analytics',
'export_csv' => 'Export CSV',
'edit_template' => 'Edit Template',
'back_to_list' => 'Back to List',
'template_not_found' => 'Template not found.',
'english_required' => 'English subject and body are required.',
'template_updated' => 'Template updated successfully.',
'english_version' => 'English',
'arabic_version' => 'Arabic',
'email_subject' => 'Email Subject',
'email_body' => 'Email Body',
'email_body_help' => 'Use placeholders like {shipment_id}, {user_name}, {offer_price}.',
'whatsapp_body' => 'WhatsApp Body',
'event_name' => 'Event Name',
'subject_en' => 'Subject (EN)',
'subject_ar' => 'Subject (AR)',
'is_company_checkbox' => 'Register as a company?',
'ctr_number' => 'CTR Number',
'ctr_document' => 'CTR Document',
'notes' => 'Notes',
'profile' => 'Profile',
'view_full_size' => 'View Full Size',
'no_trucks_found' => 'No trucks found.',
'create_shipper' => 'Create Shipper',
'create_owner' => 'Create Truck Owner',
'create_success' => 'User created successfully.',
'add_truck' => 'Add Truck',
'new_truck_details' => 'New Truck Details',
'reg_expiry' => 'Reg. Expiry',
'ins_expiry' => 'Ins. Expiry',
'registration_doc' => 'Registration Doc',
'shipment_type' => 'Shipment Type',
'type_frozen' => 'Frozen',
'type_cold' => 'Cold',
'type_dry' => 'Dry',
),
"ar" => array (
'app_name' => 'CargoLink',
'nav_home' => 'نظرة عامة',
'nav_login' => 'تسجيل الدخول',
'nav_shipper' => 'لوحة الشاحن',
'nav_owner' => 'لوحة مالك الشاحنة',
'nav_admin' => 'لوحة الإدارة',
'nav_theme' => 'المظهر',
'nav_get_started' => 'ابدأ الآن',
'hero_title' => 'انقل شحنتك بسرعة مع شاحنات موثوقة.',
'hero_subtitle' => 'أنشئ شحنة، استلم عروضاً، وادفع عبر ثواني أو التحويل البنكي.',
'hero_tagline' => 'منصة لوجستية متعددة اللغات',
'register_shipper' => 'التسجيل كشاحن',
'register_owner' => 'التسجيل كمالك شاحنة',
'cta_shipper' => 'إنشاء شحنة',
'cta_owner' => 'البحث عن الشحنات',
'cta_admin' => 'الدخول للإدارة',
'stats_shipments' => 'الشحنات المنشورة',
'stats_offers' => 'العروض الحالية',
'stats_confirmed' => 'الرحلات المؤكدة',
'section_workflow' => 'طريقة العمل',
'recent_shipments' => 'أحدث الشحنات',
'step_post' => 'يقوم الشاحن بإدخال تفاصيل الشحنة وطريقة الدفع.',
'step_offer' => 'يرسل أصحاب الشاحنات أفضل عروضهم.',
'step_confirm' => 'تؤكد الإدارة الحجز وتحدث الحالة.',
'step_confirm_desc' => 'حجز آمن وتتبع التسليم حتى الانتهاء.',
'shipper_dashboard' => 'لوحة الشاحن',
'new_shipment' => 'إنشاء شحنة',
'shipper_name' => 'اسم الشاحن',
'shipper_company' => 'الشركة',
'origin' => 'مدينة الانطلاق',
'destination' => 'مدينة الوصول',
'cargo' => 'وصف الحمولة',
'cargo_placeholder' => 'مثال: 20 منصة إلكترونيات',
'weight' => 'الوزن (طن)',
'pickup_date' => 'تاريخ الاستلام',
'delivery_date' => 'تاريخ التسليم',
'payment_method' => 'طريقة الدفع',
'payment_thawani' => 'الدفع الإلكتروني عبر ثواني',
'payment_bank' => 'تحويل بنكي',
'submit_shipment' => 'إرسال الشحنة',
'shipments_list' => 'أحدث الشحنات',
'status' => 'الحالة',
'offer' => 'أفضل عرض',
'actions' => 'إجراءات',
'view' => 'عرض',
'owner_dashboard' => 'لوحة مالك الشاحنة',
'available_shipments' => 'الشحنات المتاحة',
'offer_price' => 'سعر العرض',
'offer_owner' => 'اسم مالك الشاحنة',
'submit_offer' => 'إرسال العرض',
'admin_dashboard' => 'لوحة الإدارة',
'update_status' => 'تحديث الحالة',
'save' => 'حفظ',
'shipment_detail' => 'تفاصيل الشحنة',
'created_at' => 'تم الإنشاء',
'best_offer' => 'أفضل عرض',
'assign_owner' => 'المالك المعتمد',
'no_shipments' => 'لا توجد شحنات بعد. ابدأ بإنشاء أول شحنة.',
'no_offers' => 'لا توجد عروض بعد.',
'success_shipment' => 'تم نشر الشحنة بنجاح.',
'success_offer' => 'تم إرسال العرض إلى الشاحن.',
'success_status' => 'تم تحديث الحالة.',
'error_required' => 'يرجى تعبئة جميع الحقول المطلوبة.',
'error_invalid' => 'يرجى إدخال قيم صحيحة.',
'status_posted' => 'منشورة',
'status_offered' => 'بعرض',
'status_confirmed' => 'مؤكدة',
'status_in_transit' => 'قيد النقل',
'status_delivered' => 'تم التسليم',
'footer_note' => 'هذه هي النسخة الأولية. الدفع غير متصل بعد.',
'marketing_title_1' => 'للشاحنين',
'marketing_desc_1' => 'ابحث عن الشاحنة المناسبة لحمولتك بسرعة وأمان.',
'marketing_title_2' => 'لأصحاب الشاحنات',
'marketing_desc_2' => 'عظّم أرباحك وتجنب العودة فارغاً.',
'motivation_phrase' => 'تمكين الخدمات اللوجستية للمستقبل.',
'why_choose_us' => 'لماذا تختار كارجو لينك؟',
'feature_1_title' => 'مطابقة سريعة',
'feature_1_desc' => 'تواصل مع الشاحنات المتاحة في دقائق.',
'feature_2_title' => 'مدفوعات آمنة',
'feature_2_desc' => 'معاملاتك محمية بأعلى معايير الأمان.',
'feature_3_title' => 'مستخدمون موثوقون',
'feature_3_desc' => 'نقوم بالتحقق من جميع أصحاب الشاحنات لضمان راحتك.',
'view_faq' => 'عرض الأسئلة الشائعة',
'faq_title' => 'لديك أسئلة؟',
'faq_subtitle' => 'اطلع على الأسئلة الشائعة لمعرفة المزيد حول كيفية عمل منصتنا.',
'motivation_title' => 'هل أنت مستعد لتحويل خدماتك اللوجستية؟',
'motivation_subtitle' => 'انضم إلى منصتنا اليوم للعثور على شاحنات موثوقة أو تأمين أفضل الشحنات في السوق.',
'company' => 'الشركة',
'about_us' => 'معلومات عنا',
'careers' => 'الوظائف',
'contact' => 'اتصل بنا',
'resources' => 'الموارد',
'help_center' => 'مركز المساعدة / الأسئلة الشائعة',
'terms_of_service' => 'شروط الخدمة',
'privacy_policy' => 'سياسة الخصوصية',
'language' => 'اللغة',
'all_rights_reserved' => 'جميع الحقوق محفوظة.',
'dashboard' => 'لوحة القيادة',
'shipments' => 'الشحنات',
'reports' => 'التقارير',
'summary_report' => 'تقرير ملخص',
'shipments_by_origin_country' => 'الشحنات حسب بلد المنشأ',
'shipments_by_dest_country' => 'الشحنات حسب بلد الوجهة',
'shipments_by_origin_city' => 'الشحنات حسب مدينة المنشأ',
'shipments_by_dest_city' => 'الشحنات حسب مدينة الوجهة',
'shipments_by_shipper' => 'الشحنات حسب الشاحن',
'generated' => 'تم الإنشاء',
'report_type' => 'نوع التقرير',
'period' => 'الفترة',
'analyze_performance' => 'تحليل أداء المنصة والمقاييس.',
'print' => 'طباعة',
'start_date' => 'تاريخ البدء',
'end_date' => 'تاريخ الانتهاء',
'apply_filter' => 'تطبيق الفلتر',
'no_paid_shipments' => 'لم يتم العثور على شحنات مدفوعة لهذه الفترة.',
'name' => 'الاسم',
'total_amount' => 'المبلغ الإجمالي',
'profit' => 'الربح',
'total_label' => 'المجموع',
'printed_by' => 'طبع بواسطة',
'analytics' => 'التحليلات',
'shipper_shipments' => 'شحنات الشاحنين',
'truck_owners_statements' => 'كشوف حساب أصحاب الشاحنات',
'nav_platform_users' => 'مستخدمو المنصة',
'settings' => 'الإعدادات',
'company_setting' => 'إعدادات الشركة',
'integrations' => 'التكاملات',
'notification_templates' => 'قوالب الإشعارات',
'locations' => 'المواقع',
'countries' => 'البلدان',
'cities' => 'المدن',
'users' => 'المستخدمون',
'shippers' => 'الشاحنون',
'truck_owners' => 'أصحاب الشاحنات',
'trucks' => 'الشاحنات',
'view_truck_docs_in_edit' => 'عرض مستندات الشاحنة في صفحة التعديل.',
'user_registration' => 'تسجيل المستخدم',
'pages' => 'الصفحات',
'faqs' => 'الأسئلة الشائعة',
'landing_pages' => 'إعدادات الصفحة الرئيسية',
'edit_homepage' => 'تعديل محتوى الصفحة الرئيسية والأقسام',
'view_details' => 'عرض التفاصيل',
'manage_shippers' => 'إدارة الشاحنين',
'manage_registered_shippers' => 'إدارة الشاحنين المسجلين.',
'search_placeholder_shipper' => 'ابحث بالاسم، البريد، الشركة...',
'all_statuses' => 'كل الحالات',
'pending' => 'قيد الانتظار',
'rejected' => 'مرفوض',
'active' => 'نشط',
'no_shippers_criteria' => 'لم يتم العثور على شاحنين مطابقين لمعاييرك.',
'no_shippers_registered' => 'لا يوجد شاحنين مسجلين بعد.',
'name_company' => 'الاسم / الشركة',
'location' => 'الموقع',
'edit_shipper' => 'تعديل الشاحن',
'approve' => 'موافقة',
'reject' => 'رفض',
'delete' => 'حذف',
'delete_confirm_shipper' => 'هل أنت متأكد من حذف هذا الشاحن نهائياً؟',
'loading' => 'جاري التحميل...',
'manage_truck_owners' => 'إدارة أصحاب الشاحنات',
'review_registrations' => 'مراجعة التسجيلات والموافقة على أصحاب الشاحنات.',
'search_placeholder_owner' => 'ابحث بالاسم، البريد، اللوحة...',
'no_owners_criteria' => 'لم يتم العثور على أصحاب شاحنات مطابقين لمعاييرك.',
'no_owners_registered' => 'لا يوجد أصحاب شاحنات مسجلين بعد.',
'name_email' => 'الاسم / البريد',
'truck_info' => 'معلومات الشاحنة',
'documents' => 'المستندات',
'view_docs' => 'عرض المستندات',
'edit_owner' => 'تعديل المالك',
'delete_confirm_owner' => 'هل أنت متأكد من حذف مالك الشاحنة هذا نهائياً؟',
'docs_for' => 'مستندات',
'truck_reg' => 'تسجيل الشاحنة',
'no_picture' => 'لا توجد صورة محملة.',
'cap' => 'السعة',
'manage_shipments' => 'إدارة الشحنات',
'shipments_header' => 'الشحنات',
'shipments_subtitle' => 'إدارة جميع الشحنات عبر المنصة.',
'flash_shipment_deleted' => 'تم حذف الشحنة بنجاح.',
'search_shipments_placeholder' => 'البحث في الشحنات...',
'search_label' => 'بحث',
'sort_by' => 'ترتيب حسب',
'sort_newest' => 'الأحدث أولاً',
'sort_oldest' => 'الأقدم أولاً',
'sort_pickup_soonest' => 'تاريخ الاستلام (الأقرب)',
'sort_pickup_latest' => 'تاريخ الاستلام (الأبعد)',
'no_shipments_found_criteria' => 'لم يتم العثور على شحنات مطابقة لمعايير البحث.',
'no_shipments_platform' => 'لا توجد شحنات على المنصة بعد.',
'id_col' => 'المعرف',
'dates_col' => 'التواريخ',
'from_label' => 'من:',
'to_label' => 'إلى:',
'pick_label' => 'استلام:',
'drop_label' => 'تسليم:',
'view_shipment' => 'عرض الشحنة',
'edit_shipment_tooltip' => 'تعديل الشحنة',
'confirm_delete_shipment' => 'حذف هذه الشحنة؟',
'showing' => 'عرض',
'of' => 'من',
'previous' => 'السابق',
'next' => 'التالي',
'error_occurred' => 'حدث خطأ',
'failed_load_form' => 'فشل تحميل النموذج.',
'edit_shipment_title' => 'تعديل الشحنة #',
'update_shipment_details' => 'تحديث تفاصيل الشحنة والحالة.',
'shipment_not_found' => 'الشحنة غير موجودة',
'shipment_updated_success' => 'تم تحديث الشحنة بنجاح.',
'invalid_id' => 'معرف غير صحيح',
'back' => 'رجوع',
'shipment_details' => 'تفاصيل الشحنة',
'origin_country' => 'بلد الانطلاق',
'destination_country' => 'بلد الوصول',
'select_country_placeholder' => 'اختر البلد',
'select_city_placeholder' => 'اختر المدينة',
'loading_cities' => 'جاري التحميل...',
'error_loading_cities' => 'خطأ في تحميل المدن',
'cancel' => 'إلغاء',
'my_profile' => 'ملفي الشخصي',
'profile_picture' => 'صورة الملف الشخصي',
'change_picture' => 'تغيير الصورة',
'picture_hint' => 'انقر على أيقونة الكاميرا للتحديث.',
'full_name' => 'الاسم الكامل',
'email_address' => 'البريد الإلكتروني',
'email_hint' => 'لا يمكن تغيير البريد الإلكتروني.',
'account_role' => 'نوع الحساب',
'change_password' => 'تغيير كلمة المرور',
'new_password' => 'كلمة المرور الجديدة',
'confirm_password' => 'تأكيد كلمة المرور',
'save_changes' => 'حفظ التغييرات',
'passwords_do_not_match' => 'كلمات المرور غير متطابقة.',
'password_too_short' => 'يجب أن تكون كلمة المرور 6 أحرف على الأقل.',
'profile_updated' => 'تم تحديث الملف الشخصي بنجاح.',
'password_updated' => 'تم تحديث كلمة المرور بنجاح.',
'upload_failed' => 'فشل تحميل الملف.',
'invalid_image' => 'تنسيق الصورة غير صالح. المسموح: JPG, PNG, GIF, WEBP.',
'login_title' => 'تسجيل الدخول',
'login_subtitle' => 'الدخول إلى حسابك',
'forgot_password' => 'نسيت كلمة المرور؟',
'email_placeholder' => 'name@example.com',
'password_placeholder' => 'أدخل كلمة المرور',
'sign_in' => 'تسجيل الدخول',
'dont_have_account' => 'ليس لديك حساب؟',
'register_now' => 'سجل الآن',
'reset_password_title' => 'إعادة تعيين كلمة المرور',
'reset_password_subtitle' => 'أدخل بريدك الإلكتروني لتلقي رابط إعادة التعيين',
'send_reset_link' => 'إرسال رابط إعادة التعيين',
'back_to_login' => 'العودة لتسجيل الدخول',
'timezone' => 'المنطقة الزمنية',
'whatsapp_settings' => 'إعدادات واتساب',
'enable_whatsapp' => 'تفعيل إشعارات واتساب',
'wablas_domain' => 'نطاق Wablas',
'wablas_api_token' => 'رمز API لـ Wablas',
'reg_title' => 'إنشاء حساب جديد',
'reg_subtitle' => 'أنشئ حساباً للبدء',
'reg_success_pending' => 'تم التسجيل بنجاح. حسابك بانتظار الموافقة.',
'reg_success' => 'تم التسجيل بنجاح. يمكنك تسجيل الدخول الآن.',
'role' => 'نوع الحساب',
'shipper' => 'شاحن',
'truck_owner' => 'مالك شاحنة',
'email' => 'البريد الإلكتروني',
'password' => 'كلمة المرور',
'phone' => 'رقم الهاتف',
'country' => 'الدولة',
'select_country' => 'اختر الدولة',
'city' => 'المدينة',
'select_city' => 'اختر المدينة',
'address' => 'العنوان',
'shipper_details' => 'تفاصيل الشاحن',
'company_name' => 'اسم الشركة',
'truck_details' => 'تفاصيل الشاحنة',
'truck_type' => 'نوع الشاحنة',
'load_capacity' => 'سعة الحمولة (طن)',
'plate_no' => 'رقم اللوحة',
'bank_account' => 'رقم الحساب البنكي',
'bank_name' => 'اسم البنك',
'bank_branch' => 'اسم الفرع',
'id_card_front' => 'البطاقة الشخصية (أمام)',
'id_card_back' => 'البطاقة الشخصية (خلف)',
'truck_reg_front' => 'ملكية الشاحنة (أمام)',
'truck_reg_back' => 'ملكية الشاحنة (خلف)',
'truck_picture' => 'صورة الشاحنة',
'create_account' => 'إنشاء حساب',
'back_to_admin' => 'العودة للإدارة',
'back_to_home' => 'العودة للرئيسية',
'total_revenue' => 'إجمالي الإيرادات',
'shipments_analytics' => 'تحليلات الشحنات',
'export_csv' => 'تصدير CSV',
'edit_template' => 'تعديل القالب',
'back_to_list' => 'العودة للقائمة',
'template_not_found' => 'القالب غير موجود.',
'english_required' => 'موضوع ونص البريد الإنجليزي مطلوبان.',
'template_updated' => 'تم تحديث القالب بنجاح.',
'english_version' => 'الإنجليزية',
'arabic_version' => 'العربية',
'email_subject' => 'موضوع البريد الإلكتروني',
'email_body' => 'نص البريد الإلكتروني',
'email_body_help' => 'استخدم المتغيرات مثل {shipment_id}, {user_name}, {offer_price}.',
'whatsapp_body' => 'نص الواتساب',
'event_name' => 'اسم الحدث',
'subject_en' => 'الموضوع (إنجليزي)',
'subject_ar' => 'الموضوع (عربي)',
'is_company_checkbox' => 'هل التسجيل كشركة؟',
'ctr_number' => 'رقم السجل التجاري (CTR)',
'ctr_document' => 'وثيقة السجل التجاري',
'notes' => 'ملاحظات',
'profile' => 'الملف الشخصي',
'view_full_size' => 'عرض بالحجم الكامل',
'no_trucks_found' => 'لم يتم العثور على شاحنات.',
'create_shipper' => 'إنشاء شاحن',
'create_owner' => 'إنشاء مالك شاحنة',
'create_success' => 'تم إنشاء المستخدم بنجاح.',
'add_truck' => 'إضافة شاحنة',
'new_truck_details' => 'تفاصيل الشاحنة الجديدة',
'reg_expiry' => 'انتهاء التسجيل',
'ins_expiry' => 'انتهاء التأمين',
'registration_doc' => 'وثيقة التسجيل',
'shipment_type' => 'نوع الشحنة',
'type_frozen' => 'مجمد',
'type_cold' => 'مبرد',
'type_dry' => 'جاف',
)
];
function t(string $key): string
{
global $translations, $lang;
return $translations[$lang][$key] ?? ucwords(str_replace('_', ' ', $key));
}
function e($value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
function ensure_schema(): void
{
try { db()->exec("ALTER TABLE shipments ADD COLUMN pod_path VARCHAR(255) NULL AFTER offer_owner"); } catch (Exception $e) {}
db()->exec("\n CREATE TABLE IF NOT EXISTS landing_sections (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
subtitle TEXT NULL,
content TEXT NULL,
image_path VARCHAR(255) NULL,
layout ENUM('text_left', 'text_right', 'center') NOT NULL DEFAULT 'text_left',
button_text VARCHAR(100) NULL,
button_link VARCHAR(255) NULL,
section_order INT NOT NULL DEFAULT 0,
is_active TINYINT(1) NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
");
try { db()->exec("ALTER TABLE landing_sections ADD COLUMN title_ar VARCHAR(255) NULL AFTER title"); } catch (Exception $e) {}
try { db()->exec("ALTER TABLE landing_sections ADD COLUMN subtitle_ar TEXT NULL AFTER subtitle"); } catch (Exception $e) {}
try { db()->exec("ALTER TABLE landing_sections ADD COLUMN content_ar TEXT NULL AFTER content"); } catch (Exception $e) {}
try { db()->exec("ALTER TABLE landing_sections ADD COLUMN button_text_ar VARCHAR(100) NULL AFTER button_text"); } catch (Exception $e) {}
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS shipments (
id INT AUTO_INCREMENT PRIMARY KEY,
shipper_name VARCHAR(120) NOT NULL,
shipper_company VARCHAR(120) NOT NULL,
origin_city VARCHAR(120) NOT NULL,
destination_city VARCHAR(120) NOT NULL,
cargo_description VARCHAR(255) NOT NULL,
weight_tons DECIMAL(10,2) NOT NULL,
pickup_date DATE NOT NULL,
delivery_date DATE NOT NULL,
payment_method ENUM('thawani','bank_transfer') NOT NULL DEFAULT 'thawani',
status ENUM('posted','offered','confirmed','in_transit','delivered') NOT NULL DEFAULT 'posted',
offer_price DECIMAL(10,2) DEFAULT NULL,
offer_owner VARCHAR(120) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SQL;
db()->exec($sql);
try { db()->exec("ALTER TABLE users ADD COLUMN status ENUM('pending','active','rejected') NOT NULL DEFAULT 'active'"); } catch (Exception $e) {}
try { db()->exec("ALTER TABLE users ADD COLUMN profile_picture VARCHAR(255) NULL AFTER full_name"); } catch (Exception $e) {}
// Payment fields for shipments
try { db()->exec("ALTER TABLE shipments ADD COLUMN platform_fee DECIMAL(10,2) DEFAULT 0.00 AFTER offer_price"); } catch (Exception $e) {}
try { db()->exec("ALTER TABLE shipments ADD COLUMN total_price DECIMAL(10,2) DEFAULT 0.00 AFTER platform_fee"); } catch (Exception $e) {}
try { db()->exec("ALTER TABLE shipments ADD COLUMN payment_status ENUM('unpaid', 'paid') DEFAULT 'unpaid' AFTER status"); } catch (Exception $e) {}
db()->exec(
"CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
full_name VARCHAR(255) NOT NULL,
role ENUM('admin','shipper','truck_owner') NOT NULL,
status ENUM('pending','active','rejected') NOT NULL DEFAULT 'active',
profile_picture VARCHAR(255) NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
);
db()->exec(
"CREATE TABLE IF NOT EXISTS shipper_profiles (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL UNIQUE,
company_name VARCHAR(255) NOT NULL,
phone VARCHAR(40) NOT NULL,
country_id INT NULL,
city_id INT NULL,
address_line VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_shipper_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
);
db()->exec(
"CREATE TABLE IF NOT EXISTS truck_owner_profiles (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL UNIQUE,
phone VARCHAR(40) NOT NULL,
country_id INT NULL,
city_id INT NULL,
address_line VARCHAR(255) NOT NULL,
truck_type VARCHAR(120) NOT NULL,
load_capacity DECIMAL(10,2) NOT NULL,
plate_no VARCHAR(80) NOT NULL,
bank_account VARCHAR(100) NULL,
bank_name VARCHAR(100) NULL,
bank_branch VARCHAR(100) NULL,
id_card_path TEXT NOT NULL,
truck_pic_path VARCHAR(255) NOT NULL,
registration_path TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_owner_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
);
}
function set_flash(string $type, string $message): void
{
$_SESSION['flash'] = ['type' => $type, 'message' => $message];
}
function get_flash(): ?array
{
if (!empty($_SESSION['flash'])) {
$flash = $_SESSION['flash'];
unset($_SESSION['flash']);
return $flash;
}
return null;
}
function url_with_lang(string $path, array $params = []): string
{
global $lang;
$params = array_merge(['lang' => $lang], $params);
return $path . '?' . http_build_query($params);
}
function current_url_with_lang(string $newLang): string
{
$params = $_GET;
$params['lang'] = $newLang;
$path = basename($_SERVER['PHP_SELF'] ?? 'index.php');
return $path . '?' . http_build_query($params);
}
function status_label(string $status): string
{
$map = [
'posted' => t('status_posted'),
'offered' => t('status_offered'),
'confirmed' => t('status_confirmed'),
'in_transit' => t('status_in_transit'),
'delivered' => t('status_delivered'),
];
return $map[$status] ?? $status;
}
function get_settings(): array
{
static $settings = null;
if ($settings !== null) {
return $settings;
}
$settings = [];
try {
$stmt = db()->query("SELECT setting_key, setting_value FROM settings");
while ($row = $stmt->fetch()) {
$settings[$row['setting_key']] = $row['setting_value'];
}
} catch (Throwable $e) {}
return $settings;
}
function get_setting(string $key, $default = ''): string
{
$settings = get_settings();
return $settings[$key] ?? $default;
}
function has_permission(string $permissionSlug, ?int $userId = null): bool
{
if ($userId === null) {
if (!isset($_SESSION['user_id'])) {
return false;
}
$userId = $_SESSION['user_id'];
}
static $cache = [];
$key = $userId . ':' . $permissionSlug;
if (isset($cache[$key])) {
return $cache[$key];
}
try {
$stmt = db()->prepare(
"SELECT 1
FROM user_permissions up
JOIN permissions p ON up.permission_id = p.id
WHERE up.user_id = ? AND p.slug = ?"
);
$stmt->execute([$userId, $permissionSlug]);
$result = (bool) $stmt->fetchColumn();
$cache[$key] = $result;
return $result;
} catch (Throwable $e) {
return false;
}
}
function format_currency(float $amount): string
{
return number_format($amount, 3) . ' OMR';
}
function require_login(): void
{
if (!isset($_SESSION['user_id'])) {
header('Location: ' . url_with_lang('login.php'));
exit;
}
}
function require_role(string $role): void
{
require_login();
if ($_SESSION['user_role'] !== $role && $_SESSION['user_role'] !== 'admin') {
http_response_code(403);
die("Access Denied. You must be a " . ucfirst($role) . " to view this page.");
}
}
function generate_csrf_token(): string
{
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
function csrf_field(): string
{
$token = generate_csrf_token();
return '<input type="hidden" name="csrf_token" value="' . $token . '">';
}
function validate_csrf_token(): void
{
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
http_response_code(403);
die("CSRF validation failed. Please refresh the page and try again.");
}
}
}
// Set timezone from settings
try {
$tz = get_setting('timezone', 'UTC');
if ($tz && in_array($tz, DateTimeZone::listIdentifiers())) {
date_default_timezone_set($tz);
}
} catch (Throwable $e) {}