این سند شامل قوانین، استانداردها و اصول مهندسی الزامی برای توسعه بخش پنل مدیریت ادمین (`aqila_panel`) است.
---
## ۱. استانداردهای توسعه رابط کاربری و معماری
- **فناوری و ساختار:** پروژه بر پایه Vite + React + TypeScript توسعه یافته است.
- **تایپوگرافی و جهت متن (RTL/LTR):** رعایت فونتهای `Vazirmatn` و `Plus Jakarta Sans`، استفاده از `rtlUtils.ts` جهت تشخیص خودکار جهت متن ورودی کاربران و حفظ ثبات کرسر.
- **چندزبانه بودن کامل پنل مدیریت (۳ زبان):** پنل مدیریت منحصراً از ۳ زبان (`fa` فارسی، `ar` عربی، `en` انگلیسی) در مسیر `src/locales/` استفاده میکند. تمام متون جدولها، فیلدها، دکمهها و نشانها باید در هر ۳ فایل دیکشنری زبان (`fa.json`, `ar.json`, `en.json`) تعریف و همگام شوند.
- **قانون هماهنگی ترجمه:** هیچ تغییری نباید تکزبانه باشد؛ هر کلید جدید یا اصلاحشده در یکی از این ۳ زبان باید همزمان در دو زبان دیگر اعمال شود تا تست `locales.test.ts` کاملاً پاس شود و هیچ کلید ناقص یا نامتعادلی وجود نداشته باشد.
---
## ۲. بررسی الزامی سلامت و ران بودن پروژه پس از هر تغییر کد (Mandatory Runtime Check)
در انتهای هر پاسخ، تسک یا پیامی که در آن کدی ایجاد یا تغییر داده میشود:
- **بررسی سریع و بلادرنگ ران بودن پنل مدیریت (Immediate Runtime & Health Check):**
- بلافاصله بررسی شود که تغییرات در کامپوننتها، هوکها، تایپها یا استایلها باعث خطای کامپایل TypeScript، خطای بیلد Vite یا کرش داشبورد نشده باشد.
- سلامت ران بودن با بررسی تایپها (`npm run typecheck` / `tsc --noEmit`) یا وضعیت سرور Vite تضمین شود.
- **رفع فوری مشکل تا بازگشت به وضعیت ران (Self-Healing & Auto-Fix):**
- در صورتی که تغییر کد باعث بروز هرگونه خطا، شکست کامپایل یا توقف ران بودن پنل شود، بلافاصله باید منشأ ارور شناسایی و اصلاح گردد تا پنل مدیریت مجدداً در حالت ران، سالم و پایدار قرار گیرد.
"ticketDragDropPrompt":"اسحب ملف التذكرة وأفلته هنا أو اختره من الزر أدناه",
"ticketSupportedFormats":"الصيغ المدعومة: PDF, PNG, JPG (الحد الأقصى ۱۰ ميجابايت)",
"ticketAutoApproveNotice":"ملاحظة: رفع ملف التذكرة إلزامي لتغيير الحالة إلى «مؤكدة / مدفوعة». بعد الرفع، يرجى الضغط على «حفظ الحالة» للاعتماد النهائي.",
"ticketAutoApproveNotice":"ملاحظة: رفع ملف التذكرة إلزامي لتغيير الحالة إلى «مؤكدة / مدفوعة». بعد الرفع، ستتغير الحالة إلى «مؤكدة»؛ ثم اضغط على «تأكيد وحفظ» للاعتماد النهائي.",
"ticketUploadSuccessPendingSave":"تم تحميل ملف التذكرة بنجاح. تم تغيير الحالة إلى «مؤكدة / مدفوعة»؛ يرجى الضغط على «تأكيد وحفظ» للاعتماد.",
"confirmAndSave":"تأكيد وحفظ",
"saveStatusChanges":"حفظ تغييرات الحالة",
"reSubmitStatus":"إعادة تسجيل الحالة",
"submitStatus":"تسجيل الحالة",
"ticketRequiredTitle":"رفع التذكرة إلزامي",
"ticketRequiredForApprovedTitle":"ملف تذكرة السفر إلزامي",
"ticketRequiredForApprovedDesc":"تغيير الحالة إلى «مؤكدة / مدفوعة» يتطلب رفع ملف التذكرة الإلكترونية. يرجى أولاً رفع التذكرة من قسم «إدارة وإصدار تذكرة السفر» أدناه.",
"ticketDragDropPrompt":"Drag and drop the ticket file here or choose from the button below",
"ticketSupportedFormats":"Supported formats: PDF, PNG, JPG (up to 10MB)",
"ticketAutoApproveNotice":"Note: Uploading the ticket is required to change status to 'Approved / Paid'. After uploading, click 'Save Status' to finalize.",
"ticketAutoApproveNotice":"Note: Uploading the ticket is required to change status to 'Approved / Paid'. After uploading, the status will switch to 'Approved'; then click 'Confirm & Save' to finalize.",
"ticketUploadSuccessPendingSave":"Ticket file uploaded successfully. Status changed to 'Approved / Paid'; please click 'Confirm & Save' to finalize.",
"ticketRequiredForApprovedDesc":"Changing the status to 'Approved / Paid' requires uploading an e-ticket file. Please first upload the ticket in the 'Travel Ticket Management' section below.",
@ -660,14 +669,104 @@
"passengersList":"Passengers & Passport Images",
"passportNumber":"Passport No.",
"viewPassportImage":"View Passport",
"noPassportImage":"No Passport Image"
},
"common":{
"deleteConfirmTitle":"Confirm Deletion",
"deleteConfirmDesc":"Are you sure you want to delete this item? This action cannot be undone.",
"ticketDragDropPrompt":"فایل بلیت را اینجا بکشید و رها کنید یا از دکمه زیر انتخاب نمایید",
"ticketSupportedFormats":"فرمتهای مجاز: PDF, PNG, JPG (حداکثر ۱۰ مگابایت)",
"ticketAutoApproveNotice":"نکته: برای تغییر وضعیت به «پرداخت شده»، بارگذاری بلیت الزامی است. پس از آپلود بلیت، دکمه «ثبت وضعیت» را جهت تایید نهایی بزنید.",
"ticketAutoApproveNotice":"نکته: برای تغییر وضعیت به «پرداخت شده»، بارگذاری بلیت الزامی است. پس از آپلود بلیت، وضعیت فاکتور روی «پرداخت شده» تنظیم میشود؛ سپس دکمه «تایید و ذخیره» را جهت ثبت نهایی بزنید.",
"ticketUploadSuccessPendingSave":"فایل بلیت با موفقیت بارگذاری شد. وضعیت به «پرداخت شده» تغییر یافت؛ لطفاً دکمه «تایید و ذخیره» را بزنید.",
"confirmAndSave":"تایید و ذخیره",
"saveStatusChanges":"ذخیره تغییرات وضعیت",
"reSubmitStatus":"ثبت مجدد وضعیت",
"submitStatus":"ثبت وضعیت",
"ticketRequiredTitle":"بارگذاری بلیت الزامی است",
"ticketRequiredForApprovedTitle":"بارگذاری فایل بلیت سفر الزامی است",
"ticketRequiredForApprovedDesc":"تغییر وضعیت به «پرداخت شده» منوط به بارگذاری فایل بلیت الکترونیکی است. لطفاً ابتدا از بخش «مدیریت و صدور بلیت سفر» در پایین، فایل بلیت را آپلود نمایید.",
@ -660,14 +669,104 @@
"passengersList":"مشخصات مسافران و تصویر پاسپورت",
"passportNumber":"شماره پاسپورت",
"viewPassportImage":"مشاهده پاسپورت",
"noPassportImage":"بدون تصویر پاسپورت"
},
"common":{
"deleteConfirmTitle":"تأیید حذف",
"deleteConfirmDesc":"آیا از حذف این مورد اطمینان دارید؟ این عمل قابل بازگشت نیست.",
"yesDelete":"بله، حذف شود",
"cancel":"انصراف",
"deleting":"در حال حذف..."
"noPassportImage":"بدون تصویر پاسپورت",
"stage1Title":"مرحله ۱: بررسی و اعمال تغییرات در سفر اختصاصی",
"stage1Desc":"پروازها، هتلها، ترتیب مقاصد و قیمت را بررسی و اصلاح کنید. تا پیش از تأیید نهایی، صورتحساب مالی صادر نمیشود.",
"stage2Title":"مرحله ۲: تأیید نهایی و انتقال به صورتحسابهای مالی",
"stage2Desc":"این سفارش بررسی و نهایی شده و فاکتور آن به بخش صورتحسابهای مالی منتقل شده است.",
"invoiceTransferredBadge":"منتقلشده به صورتحساب مالی",
"notInvoicedYetBadge":"در انتظار بررسی و صدور فاکتور",
"viewInBilling":"مشاهده در صورتحسابهای مالی",
"saveStage1Review":"ذخیره تغییرات بررسی (مرحله ۱)",
"approveAndTransferToBilling":"تأیید نهایی و انتقال به صورتحسابهای مالی",
"updateInvoiceAndItems":"بهروزرسانی آیتمها و فاکتور مالی",
"rejectOrderBtn":"رد سفارش",
"addDestinationLeg":"افزودن مقصد جدید به برنامه سفر",
"moveLegUp":"جابجایی به بالا (تغییر ترتیب مقصد)",
"moveLegDown":"جابجایی به پایین (تغییر ترتیب مقصد)",
"removeLeg":"حذف این مقصد",
"selectHotelPlaceholder":"انتخاب یا تغییر هتل اقامت...",
"customHotelPlaceholder":"نام هتل دلخواه...",
"nightsLabel":"تعداد شب اقامت",
"mealPlanLabel":"برنامه غذایی",
"mealFullBoard":"فولبرد (صبحانه، ناهار، شام)",
"mealBreakfast":"همراه با صبحانه",
"mealRoomOnly":"فقط اتاق (بدون غذا)",
"finalInvoicePrice":"مبلغ نهایی فاکتور",
"requiredBadge":"اجباری",
"priceRequiredNotice":"تعیین مبلغ نهایی فاکتور اجباری است (باید بیشتر از صفر باشد).",