869 lines
54 KiB
PHP
869 lines
54 KiB
PHP
<?php if (isset($user) && $user && in_array($user['role'], ['owner', 'manager'])): ?>
|
|
<?php
|
|
$wablasInvoiceTemplate = (string) get_setting_non_empty('wablas_template_invoice', wablas_default_invoice_template());
|
|
$wablasInvoicePreviewVars = wablas_invoice_preview_vars();
|
|
$wablasDailyTemplate = (string) get_setting_non_empty('wablas_template_daily_report', wablas_default_daily_report_template());
|
|
$wablasDailyPreviewVars = wablas_daily_report_preview_vars();
|
|
$wablasReportRecipientsValue = (string) get_setting('wablas_report_recipients');
|
|
$wablasReportRecipientCount = count(wablas_parse_phone_list($wablasReportRecipientsValue)['phones']);
|
|
$wablasDailyAutoEnabled = (string) get_setting('wablas_daily_auto_send', '0') === '1';
|
|
$wablasDailyAutoTime = wablas_format_time_setting((string) get_setting('wablas_daily_auto_time', '21:00'));
|
|
$wablasDailyAutoLastDate = (string) get_setting('wablas_daily_auto_last_date', '');
|
|
$eidSerialNext = current_eid_serial_next(db());
|
|
?>
|
|
<!-- Settings Modal -->
|
|
<div class="modal fade" id="settingsModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
|
<div class="modal-content">
|
|
<form action="api/settings.php" method="POST" enctype="multipart/form-data">
|
|
<div class="modal-header">
|
|
<div class="w-100">
|
|
<div class="settings-header-toolbar">
|
|
<div class="settings-top-actions">
|
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal" dir="auto"><?= h(tr('إلغاء', 'Cancel')) ?></button>
|
|
<button type="submit" class="btn btn-primary btn-sm" dir="auto">
|
|
<i class="bi bi-save me-1"></i><?= h(tr('حفظ التغييرات', 'Save Changes')) ?>
|
|
</button>
|
|
</div>
|
|
<div class="d-flex align-items-center gap-2">
|
|
<button type="button" class="btn btn-outline-success btn-sm" data-open-wablas-settings="1">
|
|
<i class="bi bi-whatsapp me-1"></i><?= h(tr('واتساب', 'WhatsApp')) ?>
|
|
</button>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3">
|
|
<h5 class="modal-title mb-1"><?= h(tr('إعدادات الشركة', 'Company Settings')) ?></h5>
|
|
<div class="small text-muted"><?= h(tr('إعدادات واتساب أصبحت في نافذة مستقلة حتى تظهر جميع القوالب بوضوح.', 'WhatsApp settings now open in a separate popup so all templates stay visible.')) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-body pb-2">
|
|
<ul class="nav nav-tabs mb-4" id="settingsTabs" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active" id="settings-company-tab" data-bs-toggle="tab" data-bs-target="#settings-company-pane" type="button" role="tab" aria-controls="settings-company-pane" aria-selected="true">
|
|
<?= h(tr('بيانات الشركة', 'Company')) ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="settings-eid-tab" data-bs-toggle="tab" data-bs-target="#settings-eid-pane" type="button" role="tab" aria-controls="settings-eid-pane" aria-selected="false">
|
|
<?= h(tr('طلبات العيد', 'Eid Orders')) ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="settings-wablas-tab" data-bs-toggle="tab" data-bs-target="#settings-wablas-pane" type="button" role="tab" aria-controls="settings-wablas-pane" aria-selected="false">
|
|
<?= h(tr('واتساب', 'WhatsApp')) ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="settings-payment-tab" data-bs-toggle="tab" data-bs-target="#settings-payment-pane" type="button" role="tab" aria-controls="settings-payment-pane" aria-selected="false">
|
|
<?= h(tr('الدفع الإلكتروني', 'Payments')) ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="settings-email-tab" data-bs-toggle="tab" data-bs-target="#settings-email-pane" type="button" role="tab" aria-controls="settings-email-pane" aria-selected="false">
|
|
<?= h(tr('البريد الإلكتروني', 'Email')) ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="settings-policies-tab" data-bs-toggle="tab" data-bs-target="#settings-policies-pane" type="button" role="tab" aria-controls="settings-policies-pane" aria-selected="false">
|
|
<?= h(tr('السياسات والشروط', 'Policies')) ?>
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="tab-content" id="settingsTabsContent">
|
|
<div class="tab-pane fade show active" id="settings-company-pane" role="tabpanel" aria-labelledby="settings-company-tab" tabindex="0">
|
|
<div class="row g-3">
|
|
<div class="col-md-12">
|
|
<label class="form-label"><?= h(tr('المنطقة الزمنية (Timezone)', 'Timezone')) ?></label>
|
|
<select class="form-select" name="timezone" required>
|
|
<?php
|
|
$zones = timezone_identifiers_list();
|
|
$current_tz = get_setting('timezone', 'UTC');
|
|
foreach($zones as $z): ?>
|
|
<option value="<?= h($z) ?>" <?= $z === $current_tz ? 'selected' : '' ?>><?= h($z) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('اسم الشركة (عربي)', 'Company Name (AR)')) ?></label>
|
|
<input type="text" class="form-control" name="company_name_ar" value="<?= h(get_setting('company_name_ar')) ?>" required>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('اسم الشركة (إنجليزي)', 'Company Name (EN)')) ?></label>
|
|
<input type="text" class="form-control" name="company_name_en" value="<?= h(get_setting('company_name_en')) ?>" required>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('النسبة الضريبية %', 'VAT Percentage %')) ?></label>
|
|
<input type="number" step="0.01" class="form-control" name="vat_percentage" value="<?= h(get_setting('vat_percentage', 5)) ?>" required>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('الرقم الضريبي', 'VAT Number')) ?></label>
|
|
<input type="text" class="form-control" name="company_vat_number" value="<?= h(get_setting('company_vat_number')) ?>">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('رقم الهاتف', 'Phone Number')) ?></label>
|
|
<div class="input-group" dir="ltr">
|
|
<span class="input-group-text">968</span>
|
|
<input type="text" class="form-control" name="company_phone" value="<?= h(normalize_oman_phone((string) get_setting('company_phone'))) ?>" inputmode="numeric" maxlength="8" pattern="\d{8}" placeholder="91234567">
|
|
</div>
|
|
<div class="form-text"><?= h(tr('يُحفظ الرقم محلياً من 8 خانات ويُرسل مع المقدمة 968.', 'Phone is stored locally as 8 digits and sent with the 968 prefix.')) ?></div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('البريد الإلكتروني', 'Email')) ?></label>
|
|
<input type="email" class="form-control" name="company_email" value="<?= h(get_setting('company_email')) ?>">
|
|
</div>
|
|
<div class="col-md-12">
|
|
<label class="form-label"><?= h(tr('العنوان', 'Address')) ?></label>
|
|
<textarea class="form-control" name="company_address" rows="2"><?= h(get_setting('company_address')) ?></textarea>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('الشعار (Logo)', 'Logo')) ?></label>
|
|
<input type="file" class="form-control" name="company_logo" accept="image/*">
|
|
<?php if (get_setting('company_logo')): ?>
|
|
<div class="mt-2"><img src="<?= h(get_setting('company_logo')) ?>" height="50" style="background: #f8f9fa; padding: 5px; border-radius: 4px;"></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('الأيقونة (Favicon)', 'Favicon')) ?></label>
|
|
<input type="file" class="form-control" name="company_favicon" accept="image/x-icon,image/png,image/jpeg">
|
|
<?php if (get_setting('company_favicon')): ?>
|
|
<div class="mt-2"><img src="<?= h(get_setting('company_favicon')) ?>" height="32" style="background: #f8f9fa; padding: 2px; border-radius: 4px;"></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane fade" id="settings-eid-pane" role="tabpanel" aria-labelledby="settings-eid-tab" tabindex="0">
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<div class="rounded-4 border bg-body-tertiary p-3 settings-eid-card">
|
|
<div class="d-flex flex-column flex-xl-row justify-content-between align-items-xl-start gap-3 settings-eid-header-row">
|
|
<div class="flex-grow-1">
|
|
<div class="small text-uppercase text-muted mb-1"><?= h(tr('طلبات العيد', 'Eid orders')) ?></div>
|
|
<h6 class="fw-bold mb-1"><?= h(tr('إعادة ضبط التسلسل الموسمي', 'Reset seasonal serial')) ?></h6>
|
|
<p class="text-muted small mb-0"><?= h(tr('يعيد الرقم القادم لطلبات العيد إلى 1 للطلبات الجديدة فقط، بدون تغيير أرقام الطلبات السابقة.', 'Resets the next Eid order serial to 1 for new orders only, without changing older saved orders.')) ?></p>
|
|
</div>
|
|
|
|
<div class="bg-white border rounded-3 px-3 py-2 settings-eid-reset-box">
|
|
<div class="small text-muted mb-1"><?= h(tr('الرقم القادم', 'Next serial')) ?></div>
|
|
<div class="d-flex align-items-center gap-2 flex-nowrap settings-eid-inline-controls" dir="auto">
|
|
<div class="fs-5 fw-bold mb-0" data-eid-serial-next-label="1"><?= h(eid_serial_label($eidSerialNext)) ?></div>
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-danger btn-sm px-3 text-nowrap"
|
|
data-reset-eid-serial="1"
|
|
data-reset-url="<?= h(url_for('api/settings.php')) ?>"
|
|
data-reset-label="<?= h(eid_serial_label(1)) ?>"
|
|
data-reset-confirm="<?= h(tr('سيتم تعيين الرقم القادم لطلبات العيد إلى 1. لن يتم تعديل الطلبات القديمة. هل تريد المتابعة؟', 'The next Eid order serial will be reset to 1. Old orders will not be changed. Do you want to continue?')) ?>"
|
|
data-reset-success="<?= h(tr('تمت إعادة الضبط بنجاح.', 'Reset completed successfully.')) ?>"
|
|
data-reset-error="<?= h(tr('تعذر تنفيذ إعادة الضبط حالياً. حاول مرة أخرى.', 'Could not reset the Eid serial right now. Please try again.')) ?>">
|
|
<i class="bi bi-arrow-counterclockwise me-1"></i><?= h(tr('إعادة الضبط إلى 1', 'Reset to 1')) ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="settings-wablas-pane" role="tabpanel" aria-labelledby="settings-wablas-tab" tabindex="0">
|
|
<div class="rounded-4 border bg-body-tertiary p-4">
|
|
<div class="d-flex flex-column flex-lg-row justify-content-between align-items-lg-center gap-3">
|
|
<div>
|
|
<h5 class="mb-1 fw-bold"><?= h(tr('إعدادات واتساب في نافذة مستقلة', 'WhatsApp settings in a separate popup')) ?></h5>
|
|
<p class="text-muted mb-0"><?= h(tr('تم نقل جميع قوالب واتساب إلى نافذة مستقلة قابلة للتمرير حتى تظهر كل القوالب بوضوح بدون ازدحام داخل إعدادات الشركة.', 'All WhatsApp templates were moved into a separate scrollable popup so every template is clearly visible without being cramped inside Company Settings.')) ?></p>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<button type="button" class="btn btn-success" data-open-wablas-settings="1">
|
|
<i class="bi bi-whatsapp me-1"></i><?= h(tr('فتح إعدادات واتساب', 'Open WhatsApp Settings')) ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-3 mt-1">
|
|
<div class="col-md-4">
|
|
<div class="border rounded-3 bg-white p-3 h-100">
|
|
<div class="small text-muted mb-1"><?= h(tr('حالة الإرسال', 'Sending status')) ?></div>
|
|
<div class="fw-semibold"><?= h(wablas_is_enabled() ? tr('مفعل', 'Enabled') : tr('متوقف', 'Disabled')) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="border rounded-3 bg-white p-3 h-100">
|
|
<div class="small text-muted mb-1"><?= h(tr('الفواتير', 'Invoices')) ?></div>
|
|
<div class="fw-semibold"><?= h(tr('للعميل فقط', 'Customer only')) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="border rounded-3 bg-white p-3 h-100">
|
|
<div class="small text-muted mb-1"><?= h(tr('الملخص اليومي', 'Daily summary')) ?></div>
|
|
<div class="fw-semibold"><?= $wablasDailyAutoEnabled ? h($wablasDailyAutoTime . ' ' . tr('يومياً', 'daily')) : h(tr('يدوي فقط', 'Manual only')) ?></div>
|
|
<div class="small text-muted mt-1"><?= h((string) $wablasReportRecipientCount) ?> <?= h(tr('رقم مستلم', 'recipient numbers')) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="settings-payment-pane" role="tabpanel" aria-labelledby="settings-payment-tab" tabindex="0">
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<div class="border rounded-4 p-3 bg-body-tertiary">
|
|
<div class="form-check form-switch mb-2">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="thawaniEnabled" name="thawani_enabled" value="1" <?= thawani_is_enabled() ? 'checked' : '' ?>>
|
|
<label class="form-check-label fw-semibold" for="thawaniEnabled"><?= h(tr('تفعيل بوابة ثواني', 'Enable Thawani Gateway')) ?></label>
|
|
</div>
|
|
<div class="small text-muted"><?= h(tr('فعّلها ليظهر خيارا الدفع أونلاين أو الدفع لاحقاً في طلبات المتجر.', 'Enable it so the online store can offer Pay Online or Pay Later.')) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label"><?= h(tr('البيئة', 'Mode')) ?></label>
|
|
<select class="form-select" name="thawani_mode">
|
|
<option value="sandbox" <?= get_setting('thawani_mode', 'sandbox') === 'sandbox' ? 'selected' : '' ?>><?= h(tr('تجريبية (Sandbox)', 'Sandbox')) ?></option>
|
|
<option value="live" <?= get_setting('thawani_mode') === 'live' ? 'selected' : '' ?>><?= h(tr('حقيقية (Live)', 'Live')) ?></option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<label class="form-label"><?= h(tr('المفتاح العام (Publishable Key)', 'Publishable Key')) ?></label>
|
|
<input type="text" class="form-control" name="thawani_publishable_key" value="<?= h(get_setting('thawani_publishable_key')) ?>" placeholder="pk_...">
|
|
</div>
|
|
<div class="col-md-12">
|
|
<label class="form-label"><?= h(tr('المفتاح السري (Secret Key)', 'Secret Key')) ?></label>
|
|
<input type="password" class="form-control" name="thawani_secret_key" value="<?= h(get_setting('thawani_secret_key')) ?>" placeholder="sk_...">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('رابط نجاح الدفع', 'Success URL')) ?></label>
|
|
<input type="url" class="form-control" name="thawani_success_url" value="<?= h(get_setting('thawani_success_url')) ?>" placeholder="<?= h(thawani_default_return_url('success')) ?>">
|
|
<div class="form-text"><?= h(tr('اختياري. إذا تركته فارغاً سيستخدم النظام رابط الرجوع الداخلي تلقائياً.', 'Optional. Leave empty to use the built-in return URL automatically.')) ?></div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr('رابط إلغاء الدفع', 'Cancel URL')) ?></label>
|
|
<input type="url" class="form-control" name="thawani_cancel_url" value="<?= h(get_setting('thawani_cancel_url')) ?>" placeholder="<?= h(thawani_default_return_url('cancel')) ?>">
|
|
<div class="form-text"><?= h(tr('اختياري. يستخدم عندما يُلغى الدفع أو يعود العميل بدون إتمام العملية.', 'Optional. Used when payment is cancelled or the customer returns without completing checkout.')) ?></div>
|
|
</div>
|
|
<div class="col-12">
|
|
<div class="alert alert-info rounded-4 mb-0">
|
|
<div class="fw-semibold mb-1"><?= h(tr('معلومة', 'Note')) ?></div>
|
|
<div class="small mb-0"><?= h(tr('عند اختيار الدفع أونلاين سيُنشئ النظام جلسة Thawani ويرسل العميل مباشرةً لصفحة الدفع.', 'When Pay Online is selected, the system creates a Thawani session and redirects the customer to the hosted checkout page.')) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="settings-email-pane" role="tabpanel" aria-labelledby="settings-email-tab" tabindex="0">
|
|
<div class="row g-3">
|
|
<div class="col-md-12">
|
|
<h6 class="mb-0 fw-bold"><?= h(tr("إعدادات البريد الإلكتروني (SMTP)", "SMTP Email Settings")) ?></h6>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr("خادم SMTP (Host)", "SMTP Host")) ?></label>
|
|
<input type="text" class="form-control" name="smtp_host" value="<?= h(get_setting("smtp_host")) ?>">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr("منفذ SMTP (Port)", "SMTP Port")) ?></label>
|
|
<input type="number" class="form-control" name="smtp_port" value="<?= h(get_setting("smtp_port", 587)) ?>">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr("مستخدم SMTP (User)", "SMTP User")) ?></label>
|
|
<input type="text" class="form-control" name="smtp_user" value="<?= h(get_setting("smtp_user")) ?>">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr("كلمة مرور SMTP (Pass)", "SMTP Password")) ?></label>
|
|
<input type="password" class="form-control" name="smtp_pass" value="<?= h(get_setting("smtp_pass")) ?>">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr("تشفير SMTP (Secure)", "SMTP Secure (tls/ssl)")) ?></label>
|
|
<select class="form-select" name="smtp_secure">
|
|
<option value="tls" <?= get_setting("smtp_secure", "tls") === "tls" ? "selected" : "" ?>>TLS</option>
|
|
<option value="ssl" <?= get_setting("smtp_secure") === "ssl" ? "selected" : "" ?>>SSL</option>
|
|
<option value="" <?= get_setting("smtp_secure") === "" ? "selected" : "" ?>>None</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label"><?= h(tr("البريد المرسل (From Email)", "From Email")) ?></label>
|
|
<input type="email" class="form-control" name="mail_from" value="<?= h(get_setting("mail_from")) ?>">
|
|
</div>
|
|
<div class="col-md-12">
|
|
<label class="form-label"><?= h(tr("اسم المرسل (From Name)", "From Name")) ?></label>
|
|
<input type="text" class="form-control" name="mail_from_name" value="<?= h(get_setting("mail_from_name")) ?>">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade" id="settings-policies-pane" role="tabpanel" aria-labelledby="settings-policies-tab" tabindex="0">
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<div class="alert alert-light border rounded-4 mb-0">
|
|
<div class="fw-semibold mb-1"><?= h(tr('روابط التذييل', 'Footer links')) ?></div>
|
|
<div class="small text-muted mb-0"><?= h(tr('سيتم ربط صفحات سياسة الخصوصية والشروط والأحكام تلقائياً في تذييل النظام والمتجر.', 'Privacy Policy and Terms pages will be linked automatically in the admin and store footer.')) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label"><?= h(tr('سياسة الخصوصية', 'Privacy Policy')) ?></label>
|
|
<textarea class="form-control" name="privacy_policy_content" rows="12" placeholder="<?= h(tr('أدخل نص سياسة الخصوصية هنا...', 'Enter the privacy policy content here...')) ?>"><?= h(get_setting('privacy_policy_content')) ?></textarea>
|
|
<div class="form-text"><?= h(tr('يظهر هذا النص في صفحة سياسة الخصوصية العامة.', 'This content appears on the public Privacy Policy page.')) ?></div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label"><?= h(tr('الشروط والأحكام', 'Terms & Conditions')) ?></label>
|
|
<textarea class="form-control" name="terms_conditions_content" rows="12" placeholder="<?= h(tr('أدخل نص الشروط والأحكام هنا...', 'Enter the terms and conditions content here...')) ?>"><?= h(get_setting('terms_conditions_content')) ?></textarea>
|
|
<div class="form-text"><?= h(tr('يظهر هذا النص في صفحة الشروط والأحكام العامة.', 'This content appears on the public Terms & Conditions page.')) ?></div>
|
|
</div>
|
|
<div class="col-12">
|
|
<div class="settings-inline-save border rounded-4 bg-body-tertiary px-3 py-3 d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3">
|
|
<div>
|
|
<div class="fw-semibold"><?= h(tr('حفظ السياسات', 'Save policies')) ?></div>
|
|
<div class="small text-muted"><?= h(tr('يمكنك الحفظ من هنا أيضاً إذا كان زر التذييل خارج الشاشة.', 'You can also save from here if the footer action is outside the screen.')) ?></div>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary px-4 align-self-md-start">
|
|
<i class="bi bi-save me-1"></i><?= h(tr('حفظ التغييرات', 'Save Changes')) ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
#settingsModal .modal-header {
|
|
position: sticky;
|
|
z-index: 3;
|
|
background: var(--bs-body-bg);
|
|
}
|
|
|
|
#settingsModal .modal-header {
|
|
top: 0;
|
|
border-bottom: 1px solid var(--bs-border-color);
|
|
}
|
|
|
|
#settingsModal .settings-header-toolbar {
|
|
direction: ltr;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
#settingsModal .settings-top-actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
#settingsModal .modal-body {
|
|
padding-top: 0.85rem;
|
|
padding-bottom: 1rem;
|
|
}
|
|
|
|
#settingsModal .settings-eid-card {
|
|
margin-top: 0;
|
|
}
|
|
|
|
#settingsModal .settings-eid-header-row {
|
|
flex-wrap: nowrap;
|
|
}
|
|
|
|
#settingsModal .settings-eid-reset-box {
|
|
flex: 0 0 auto;
|
|
min-width: 290px;
|
|
align-self: flex-start;
|
|
}
|
|
|
|
#settingsModal .settings-eid-inline-controls {
|
|
justify-content: space-between;
|
|
}
|
|
|
|
#settingsModal .settings-inline-save {
|
|
position: sticky;
|
|
bottom: -0.5rem;
|
|
z-index: 2;
|
|
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
|
|
}
|
|
|
|
@media (max-width: 767.98px) {
|
|
#settingsModal .settings-top-actions {
|
|
width: 100%;
|
|
}
|
|
|
|
#settingsModal .settings-top-actions .btn {
|
|
flex: 1 1 0;
|
|
}
|
|
|
|
#settingsModal .settings-header-toolbar > .d-flex {
|
|
width: 100%;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
#settingsModal .settings-eid-header-row {
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
#settingsModal .settings-eid-reset-box {
|
|
width: 100%;
|
|
min-width: 0;
|
|
}
|
|
}
|
|
|
|
#wablasSettingsModal {
|
|
overflow-y: auto;
|
|
}
|
|
|
|
#wablasSettingsModal .modal-dialog {
|
|
margin: 0;
|
|
max-width: none;
|
|
min-height: 100%;
|
|
}
|
|
|
|
#wablasSettingsModal .modal-content {
|
|
min-height: 100vh;
|
|
border-radius: 0;
|
|
}
|
|
|
|
#wablasSettingsModal .modal-header,
|
|
#wablasSettingsModal .modal-footer {
|
|
position: sticky;
|
|
z-index: 3;
|
|
background: var(--bs-body-bg);
|
|
}
|
|
|
|
#wablasSettingsModal .modal-header {
|
|
top: 0;
|
|
border-bottom: 1px solid var(--bs-border-color);
|
|
}
|
|
|
|
#wablasSettingsModal .modal-footer {
|
|
bottom: 0;
|
|
border-top: 1px solid var(--bs-border-color);
|
|
}
|
|
|
|
#wablasSettingsModal .modal-body {
|
|
overflow: visible;
|
|
padding-bottom: 2rem;
|
|
}
|
|
|
|
#wablasSettingsModal .wablas-template-preview {
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
</style>
|
|
|
|
<!-- WhatsApp Settings Modal -->
|
|
<div class="modal fade" id="wablasSettingsModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-fullscreen">
|
|
<div class="modal-content border-0 rounded-0">
|
|
<form action="api/settings.php" method="POST" id="wablasSettingsForm">
|
|
<input type="hidden" name="return_modal" value="wablas">
|
|
<div class="modal-header">
|
|
<div>
|
|
<h5 class="modal-title mb-1"><?= h(tr('إعدادات واتساب', 'WhatsApp Settings')) ?></h5>
|
|
<div class="small text-muted"><?= h(tr('نافذة مستقلة قابلة للتمرير لعرض جميع القوالب والحقول بشكل واضح.', 'A dedicated scrollable popup to show all WhatsApp fields and templates clearly.')) ?></div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert d-none" id="wablasSettingsAlert" role="alert"></div>
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<div class="border rounded-4 px-3 py-3 bg-body-tertiary">
|
|
<div class="d-flex flex-column flex-lg-row justify-content-between align-items-lg-center gap-3">
|
|
<div>
|
|
<h6 class="mb-1 fw-bold"><?= h(tr('ربط Wablas', 'Wablas connection')) ?></h6>
|
|
<div class="small text-muted"><?= h(tr('فعّل الإرسال ثم احفظ، ويمكنك إرسال رسالة اختبار مباشرة من هنا.', 'Enable sending, save the settings, and send a test message directly from here.')) ?></div>
|
|
</div>
|
|
<div class="form-check form-switch m-0">
|
|
<input type="hidden" name="wablas_enabled" value="0">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="wablasEnabledSwitchModal" name="wablas_enabled" value="1" <?= wablas_is_enabled() ? 'checked' : '' ?>>
|
|
<label class="form-check-label fw-semibold" for="wablasEnabledSwitchModal"><?= h(tr('تفعيل واتساب', 'Enable WhatsApp')) ?></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1"><?= h(tr('Wablas Token', 'Wablas Token')) ?></label>
|
|
<input type="text" class="form-control" name="wablas_token" value="<?= h(get_setting('wablas_token')) ?>">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1"><?= h(tr('Wablas Secret Key', 'Wablas Secret Key')) ?></label>
|
|
<input type="password" class="form-control" name="wablas_secret_key" value="<?= h(get_setting('wablas_secret_key')) ?>">
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label mb-1"><?= h(tr('رابط بوابة Wablas', 'Wablas Gateway URL')) ?></label>
|
|
<input type="text" class="form-control" name="wablas_api_url" value="<?= h(get_setting('wablas_api_url', 'https://wablas.com/api/send-message')) ?>" placeholder="https://wablas.com/api/send-message">
|
|
<div class="small text-muted mt-1"><?= h(tr('إذا كان حسابك مربوطاً بسيرفر محدد مثل tegal.wablas.com أو texas.wablas.com فاكتب رابط ذلك السيرفر هنا. يمكنك إدخال الدومين فقط أو رابط /api/send-message الكامل.', 'If your account is tied to a specific server like tegal.wablas.com or texas.wablas.com, enter that server here. You can paste either the domain or the full /api/send-message URL.')) ?></div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label mb-1"><?= h(tr('رقم الاختبار', 'Test Phone')) ?></label>
|
|
<div class="input-group" dir="ltr">
|
|
<span class="input-group-text">968</span>
|
|
<input type="text" class="form-control" name="wablas_test_phone" value="<?= h(normalize_oman_phone((string) get_setting('company_phone'))) ?>" inputmode="numeric" maxlength="8" pattern="\d{8}" placeholder="91234567">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1"><?= h(tr('رسالة الاختبار', 'Test Message')) ?></label>
|
|
<textarea class="form-control" name="wablas_test_message" rows="2"><?= h(tr('هذه رسالة واتساب تجريبية من النظام.', 'This is a WhatsApp test message from the system.')) ?></textarea>
|
|
</div>
|
|
<div class="col-md-2 d-grid align-self-end">
|
|
<button type="submit" class="btn btn-outline-success" formaction="api/wablas_test.php" formmethod="POST">
|
|
<i class="bi bi-whatsapp me-1"></i><?= h(tr('إرسال اختبار', 'Send Test')) ?>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<div class="border rounded-4 p-3 bg-white">
|
|
<div class="d-flex flex-column flex-lg-row justify-content-between align-items-lg-start gap-2 mb-3">
|
|
<div>
|
|
<h6 class="mb-1 fw-semibold"><?= h(tr('قالب الفاتورة', 'Invoice template')) ?></h6>
|
|
<div class="small text-muted"><?= h(tr('يرسل تلقائياً إلى رقم العميل الموجود في الفاتورة فقط.', 'Sent automatically only to the customer phone saved on the invoice.')) ?></div>
|
|
</div>
|
|
<span class="badge text-bg-success-subtle border border-success-subtle text-success-emphasis"><?= h(tr('للعميل فقط', 'Customer only')) ?></span>
|
|
</div>
|
|
<div class="alert alert-light border small mb-3">
|
|
<strong><?= h(tr('مهم:', 'Important:')) ?></strong> <?= h(tr('لن يتم إرسال الفاتورة لأي رقم إداري. إذا لم يكن للعميل رقم واتساب محفوظ فلن يتم الإرسال.', 'The invoice will not be sent to any admin number. If the customer has no saved WhatsApp phone, nothing will be sent.')) ?>
|
|
</div>
|
|
<label class="form-label mb-1"><?= h(tr('قالب الفاتورة', 'Invoice Template')) ?></label>
|
|
<textarea class="form-control" id="wablasInvoiceTemplate" name="wablas_template_invoice" rows="12" data-wablas-preview-source="invoice"><?= h($wablasInvoiceTemplate) ?></textarea>
|
|
<div class="small text-muted mt-2"><?= h(tr('المتغيرات المتاحة: {receipt_no}, {customer_name}, {customer_phone}, {branch_name}, {payment_method_label}, {payment_status_label}, {total_amount}, {due_amount}, {sale_date}, {items_summary}, {notes}', 'Available placeholders: {receipt_no}, {customer_name}, {customer_phone}, {branch_name}, {payment_method_label}, {payment_status_label}, {total_amount}, {due_amount}, {sale_date}, {items_summary}, {notes}')) ?></div>
|
|
<div class="border rounded-3 bg-light-subtle p-3 mt-3">
|
|
<div class="small text-muted mb-2"><?= h(tr('معاينة مباشرة', 'Live preview')) ?></div>
|
|
<pre class="small mb-0 text-wrap wablas-template-preview" data-wablas-preview="invoice" data-preview-vars='<?= h(json_encode($wablasInvoicePreviewVars, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) ?>'><?= h(wablas_render_template($wablasInvoiceTemplate, $wablasInvoicePreviewVars)) ?></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<div class="border rounded-4 p-3 bg-white">
|
|
<div class="d-flex flex-column flex-lg-row justify-content-between align-items-lg-start gap-2 mb-3">
|
|
<div>
|
|
<h6 class="mb-1 fw-semibold"><?= h(tr('قالب الملخص اليومي', 'Daily summary template')) ?></h6>
|
|
<div class="small text-muted"><?= h(tr('يرسل إلى أرقام الإدارة المحددة فقط، ويمكن تشغيله تلقائياً كل يوم في وقت محدد.', 'Sent only to the specified management numbers, and can run automatically every day at a chosen time.')) ?></div>
|
|
</div>
|
|
<span class="badge text-bg-light border"><?= h((string) $wablasReportRecipientCount) ?> <?= h(tr('مستلمين', 'recipients')) ?></span>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-lg-6">
|
|
<label class="form-label mb-1"><?= h(tr('أرقام واتساب الملخص اليومي', 'Daily summary WhatsApp numbers')) ?></label>
|
|
<textarea class="form-control" name="wablas_report_recipients" rows="5" dir="ltr"><?= h(wablas_phone_list_for_input($wablasReportRecipientsValue)) ?></textarea>
|
|
<div class="form-text"><?= h(tr('هذه الأرقام فقط ستستلم الملخص اليومي.', 'Only these numbers will receive the daily summary.')) ?></div>
|
|
</div>
|
|
<div class="col-lg-6">
|
|
<div class="border rounded-4 bg-body-tertiary p-3 h-100">
|
|
<div class="form-check form-switch mb-3">
|
|
<input type="hidden" name="wablas_daily_auto_send" value="0">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="wablasDailyAutoSend" name="wablas_daily_auto_send" value="1" <?= $wablasDailyAutoEnabled ? 'checked' : '' ?>>
|
|
<label class="form-check-label fw-semibold" for="wablasDailyAutoSend"><?= h(tr('تفعيل الإرسال التلقائي للملخص اليومي', 'Enable automatic daily summary sending')) ?></label>
|
|
</div>
|
|
<label class="form-label mb-1" for="wablasDailyAutoTime"><?= h(tr('وقت الإرسال اليومي', 'Daily send time')) ?></label>
|
|
<input type="time" class="form-control" id="wablasDailyAutoTime" name="wablas_daily_auto_time" value="<?= h($wablasDailyAutoTime) ?>">
|
|
<div class="form-text mt-2"><?= h(tr('سيتم الإرسال مرة واحدة يومياً بعد هذا الوقت عند أول استخدام للنظام.', 'It will send once per day after this time on the first app request that day.')) ?></div>
|
|
<?php if ($wablasDailyAutoLastDate !== ''): ?>
|
|
<div class="small text-muted mt-3"><?= h(tr('آخر إرسال تلقائي:', 'Last automatic send:')) ?> <?= h($wablasDailyAutoLastDate) ?></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<label class="form-label mb-1 mt-3"><?= h(tr('قالب الملخص اليومي', 'Daily Summary Template')) ?></label>
|
|
<textarea class="form-control" id="wablasDailyTemplate" name="wablas_template_daily_report" rows="12" data-wablas-preview-source="daily"><?= h($wablasDailyTemplate) ?></textarea>
|
|
<div class="small text-muted mt-2"><?= h(tr('المتغيرات المتاحة: {report_date}, {branch_name}, {invoice_count}, {total_sales}, {seller_summary}, {outlet_summary}, {payment_summary}, {generated_at}', 'Available placeholders: {report_date}, {branch_name}, {invoice_count}, {total_sales}, {seller_summary}, {outlet_summary}, {payment_summary}, {generated_at}')) ?></div>
|
|
<div class="border rounded-3 bg-light-subtle p-3 mt-3">
|
|
<div class="small text-muted mb-2"><?= h(tr('معاينة مباشرة', 'Live preview')) ?></div>
|
|
<pre class="small mb-0 text-wrap wablas-template-preview" data-wablas-preview="daily" data-preview-vars='<?= h(json_encode($wablasDailyPreviewVars, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) ?>'><?= h(wablas_render_template($wablasDailyTemplate, $wablasDailyPreviewVars)) ?></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<div class="border rounded-4 p-3 bg-white">
|
|
<div class="d-flex flex-column flex-lg-row justify-content-between align-items-lg-center gap-2 mb-3">
|
|
<div>
|
|
<h6 class="mb-1 fw-semibold"><?= h(tr('قوالب طلبات المتجر الإلكتروني', 'Online order templates')) ?></h6>
|
|
<div class="small text-muted"><?= h(tr('هذه القوالب تُرسل لعميل الطلب حسب حالة الطلب.', 'These templates are sent to the customer depending on the order status.')) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<label class="form-label mb-1"><?= h(tr('قالب رسالة إنشاء الطلب', 'Order Created Template')) ?></label>
|
|
<textarea class="form-control" name="wablas_template_created" rows="4"><?= h(get_setting('wablas_template_created', wablas_default_order_template('created'))) ?></textarea>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1"><?= h(tr('قالب قيد الانتظار', 'Pending Template')) ?></label>
|
|
<textarea class="form-control" name="wablas_template_pending" rows="4"><?= h(get_setting('wablas_template_pending', wablas_default_order_template('pending'))) ?></textarea>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1"><?= h(tr('قالب مقبول', 'Accepted Template')) ?></label>
|
|
<textarea class="form-control" name="wablas_template_accepted" rows="4"><?= h(get_setting('wablas_template_accepted', wablas_default_order_template('accepted'))) ?></textarea>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1"><?= h(tr('قالب مكتمل', 'Completed Template')) ?></label>
|
|
<textarea class="form-control" name="wablas_template_completed" rows="4"><?= h(get_setting('wablas_template_completed', wablas_default_order_template('completed'))) ?></textarea>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1"><?= h(tr('قالب مرفوض', 'Rejected Template')) ?></label>
|
|
<textarea class="form-control" name="wablas_template_rejected" rows="4"><?= h(get_setting('wablas_template_rejected', wablas_default_order_template('rejected'))) ?></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= h(tr('إلغاء', 'Cancel')) ?></button>
|
|
<button type="submit" class="btn btn-success"><?= h(tr('حفظ إعدادات واتساب', 'Save WhatsApp Settings')) ?></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
var settingsModalEl = document.getElementById('settingsModal');
|
|
var wablasModalEl = document.getElementById('wablasSettingsModal');
|
|
var wablasForm = document.getElementById('wablasSettingsForm');
|
|
var wablasAlertEl = document.getElementById('wablasSettingsAlert');
|
|
var reopenSettingsAfterWablas = false;
|
|
|
|
var showWablasAlert = function (type, message) {
|
|
if (!wablasAlertEl) {
|
|
return;
|
|
}
|
|
var alertClass = type === 'success' ? 'alert-success' : (type === 'warning' ? 'alert-warning' : 'alert-danger');
|
|
wablasAlertEl.className = 'alert ' + alertClass;
|
|
wablasAlertEl.textContent = message || '';
|
|
wablasAlertEl.classList.remove('d-none');
|
|
};
|
|
|
|
var clearWablasAlert = function () {
|
|
if (!wablasAlertEl) {
|
|
return;
|
|
}
|
|
wablasAlertEl.className = 'alert d-none';
|
|
wablasAlertEl.textContent = '';
|
|
};
|
|
|
|
document.querySelectorAll('[data-open-wablas-settings]').forEach(function (trigger) {
|
|
trigger.addEventListener('click', function () {
|
|
if (!wablasModalEl || typeof bootstrap === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
var wablasModal = bootstrap.Modal.getOrCreateInstance(wablasModalEl);
|
|
if (settingsModalEl && settingsModalEl.classList.contains('show')) {
|
|
reopenSettingsAfterWablas = true;
|
|
settingsModalEl.addEventListener('hidden.bs.modal', function handleSettingsHidden() {
|
|
settingsModalEl.removeEventListener('hidden.bs.modal', handleSettingsHidden);
|
|
wablasModal.show();
|
|
});
|
|
bootstrap.Modal.getOrCreateInstance(settingsModalEl).hide();
|
|
return;
|
|
}
|
|
|
|
wablasModal.show();
|
|
});
|
|
});
|
|
|
|
if (settingsModalEl && wablasModalEl && typeof bootstrap !== 'undefined') {
|
|
wablasModalEl.addEventListener('hidden.bs.modal', function () {
|
|
clearWablasAlert();
|
|
if (!reopenSettingsAfterWablas) {
|
|
return;
|
|
}
|
|
reopenSettingsAfterWablas = false;
|
|
bootstrap.Modal.getOrCreateInstance(settingsModalEl).show();
|
|
});
|
|
}
|
|
|
|
if (wablasModalEl && typeof bootstrap !== 'undefined') {
|
|
var wablasUrl = new URL(window.location.href);
|
|
if (wablasUrl.searchParams.get('open_modal') === 'wablas') {
|
|
bootstrap.Modal.getOrCreateInstance(wablasModalEl).show();
|
|
wablasUrl.searchParams.delete('open_modal');
|
|
if (window.history && typeof window.history.replaceState === 'function') {
|
|
window.history.replaceState({}, document.title, wablasUrl.pathname + (wablasUrl.search ? '?' + wablasUrl.searchParams.toString() : '') + wablasUrl.hash);
|
|
}
|
|
}
|
|
}
|
|
|
|
document.querySelectorAll('[data-reset-eid-serial]').forEach(function (button) {
|
|
button.addEventListener('click', function () {
|
|
var actionUrl = button.getAttribute('data-reset-url') || 'api/settings.php';
|
|
var confirmMessage = button.getAttribute('data-reset-confirm') || '';
|
|
var successMessage = button.getAttribute('data-reset-success') || 'Done.';
|
|
var errorMessage = button.getAttribute('data-reset-error') || 'Request failed.';
|
|
var nextLabel = button.getAttribute('data-reset-label') || 'E-0001';
|
|
var nextLabelEl = document.querySelector('[data-eid-serial-next-label]');
|
|
|
|
var executeReset = function () {
|
|
var formData = new FormData();
|
|
formData.append('action', 'reset_eid_serial');
|
|
formData.append('return_modal', 'settings');
|
|
|
|
var originalHtml = button.innerHTML;
|
|
button.disabled = true;
|
|
button.setAttribute('aria-busy', 'true');
|
|
button.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span><?= h(tr('جارٍ التنفيذ...', 'Processing...')) ?>';
|
|
|
|
fetch(actionUrl, {
|
|
method: 'POST',
|
|
body: formData,
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
'Accept': 'application/json'
|
|
},
|
|
credentials: 'same-origin'
|
|
}).then(function (response) {
|
|
return response.json().catch(function () {
|
|
return { success: false, type: 'danger', message: errorMessage };
|
|
});
|
|
}).then(function (data) {
|
|
var ok = !!(data && data.success);
|
|
var type = data && data.type ? data.type : (ok ? 'success' : 'danger');
|
|
var message = data && data.message ? data.message : (ok ? successMessage : errorMessage);
|
|
|
|
if (ok && nextLabelEl) {
|
|
nextLabelEl.textContent = nextLabel;
|
|
}
|
|
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({
|
|
icon: type === 'success' ? 'success' : (type === 'warning' ? 'warning' : 'error'),
|
|
title: message,
|
|
toast: true,
|
|
position: 'top-end',
|
|
showConfirmButton: false,
|
|
timer: 3200,
|
|
timerProgressBar: true
|
|
});
|
|
} else if (!ok) {
|
|
window.alert(message);
|
|
}
|
|
}).catch(function () {
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({ icon: 'error', title: errorMessage, toast: true, position: 'top-end', showConfirmButton: false, timer: 3200, timerProgressBar: true });
|
|
} else {
|
|
window.alert(errorMessage);
|
|
}
|
|
}).finally(function () {
|
|
button.disabled = false;
|
|
button.removeAttribute('aria-busy');
|
|
button.innerHTML = originalHtml;
|
|
});
|
|
};
|
|
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: confirmMessage,
|
|
showCancelButton: true,
|
|
confirmButtonText: '<?= h(tr('نعم، إعادة الضبط', 'Yes, reset')) ?>',
|
|
cancelButtonText: '<?= h(tr('إلغاء', 'Cancel')) ?>'
|
|
}).then(function (result) {
|
|
if (result.isConfirmed) {
|
|
executeReset();
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (window.confirm(confirmMessage)) {
|
|
executeReset();
|
|
}
|
|
});
|
|
});
|
|
|
|
if (wablasForm && window.fetch) {
|
|
wablasForm.addEventListener('submit', function (event) {
|
|
var submitter = event.submitter;
|
|
if (!submitter) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
clearWablasAlert();
|
|
|
|
var action = submitter.getAttribute('formaction') || wablasForm.getAttribute('action') || window.location.href;
|
|
var method = submitter.getAttribute('formmethod') || wablasForm.getAttribute('method') || 'POST';
|
|
var formData = new FormData(wablasForm, submitter);
|
|
var originalHtml = submitter.innerHTML;
|
|
|
|
submitter.disabled = true;
|
|
submitter.setAttribute('aria-busy', 'true');
|
|
submitter.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span><?= h(tr('جارٍ الحفظ...', 'Saving...')) ?>';
|
|
|
|
fetch(action, {
|
|
method: method.toUpperCase(),
|
|
body: formData,
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
'Accept': 'application/json'
|
|
},
|
|
credentials: 'same-origin'
|
|
}).then(function (response) {
|
|
return response.json().catch(function () {
|
|
return { success: false, type: 'danger', message: 'Unexpected response.' };
|
|
});
|
|
}).then(function (data) {
|
|
var type = data && data.type ? data.type : (data && data.success ? 'success' : 'danger');
|
|
var message = data && data.message ? data.message : 'Request finished.';
|
|
showWablasAlert(type, message);
|
|
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({
|
|
icon: type === 'success' ? 'success' : (type === 'warning' ? 'warning' : 'error'),
|
|
title: message,
|
|
toast: true,
|
|
position: 'top-end',
|
|
showConfirmButton: false,
|
|
timer: 3000,
|
|
timerProgressBar: true
|
|
});
|
|
}
|
|
}).catch(function () {
|
|
showWablasAlert('danger', '<?= h(tr('تعذر حفظ الإعدادات حالياً. حاول مرة أخرى.', 'Could not save the settings right now. Please try again.')) ?>');
|
|
}).finally(function () {
|
|
submitter.disabled = false;
|
|
submitter.removeAttribute('aria-busy');
|
|
submitter.innerHTML = originalHtml;
|
|
});
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll('[data-wablas-preview-source]').forEach(function (field) {
|
|
var key = field.getAttribute('data-wablas-preview-source');
|
|
var preview = document.querySelector('[data-wablas-preview="' + key + '"]');
|
|
if (!preview) {
|
|
return;
|
|
}
|
|
|
|
var vars = {};
|
|
try {
|
|
vars = JSON.parse(preview.getAttribute('data-preview-vars') || '{}');
|
|
} catch (error) {
|
|
vars = {};
|
|
}
|
|
|
|
var render = function (template) {
|
|
return String(template || '').replace(/\{([a-z0-9_]+)\}/gi, function (match, token) {
|
|
return Object.prototype.hasOwnProperty.call(vars, token) ? String(vars[token]) : match;
|
|
});
|
|
};
|
|
|
|
var sync = function () {
|
|
preview.textContent = render(field.value);
|
|
};
|
|
|
|
field.addEventListener('input', sync);
|
|
sync();
|
|
});
|
|
});
|
|
</script>
|
|
<?php endif; ?>
|