fix sms and ticket user frindly
This commit is contained in:
1 parent
1ee83374fd
commit
b8b3aba855
30 files changed
+2220
-119
No files matched your search
@@ -1,24 +1,80 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}{{ page_title }}{% endblock %}
|
||||
{% block content %}<div class="operations-page operations-dispatch-detail">
|
||||
<section class="staff-page-head">
|
||||
<div><p class="eyebrow">شناسه ارسال {{ dispatch.public_id }}</p><h1>{{ dispatch.subject }}</h1><p>{{ dispatch.unit }} · گروه {{ dispatch.contact_group.name }} · {{ dispatch.recipient_count }} مخاطب</p></div>
|
||||
<div><a class="button" href="{% url 'staff_tickets:dispatch_create' %}">ارسال گروهی جدید</a>{% if metrics.failed %}<form method="post" action="{% url 'staff_tickets:dispatch_retry' dispatch.public_id %}" style="margin-top:.75rem">{% csrf_token %}<button class="button" type="submit">تلاش مجدد برای {{ metrics.failed }} ارسال ناموفق</button></form>{% endif %}</div>
|
||||
</section>
|
||||
<section class="stats-grid operations-metrics" aria-label="وضعیت ارسال گروهی"><article class="stat-card"><div class="stat-label">پیامک موفق</div><div class="stat-value">{{ metrics.sent }}</div></article><article class="stat-card"><div class="stat-label">در صف</div><div class="stat-value">{{ metrics.pending }}</div></article><article class="stat-card"><div class="stat-label">لینک مشاهدهشده</div><div class="stat-value">{{ metrics.opened }}</div></article><article class="stat-card"><div class="stat-label">پاسخ ثبتشده</div><div class="stat-value">{{ metrics.replied }}</div></article><article class="stat-card alert"><div class="stat-label">ارسال ناموفق</div><div class="stat-value">{{ metrics.failed }}</div></article></section>
|
||||
<section class="ticket-stream">
|
||||
<header class="stream-head"><div><span class="panel-index">نمای مقایسهای</span><h2>وضعیت دریافت و پاسخ مخاطبان</h2></div><span>{{ dispatch.get_status_display }}</span></header>
|
||||
<div class="table-scroll"><table><thead><tr><th>مخاطب</th><th>شماره</th><th>تیکت</th><th>وضعیت پیامک</th><th>وضعیت تیکت</th><th>بازدید لینک</th><th>پاسخ پیشنهادی</th></tr></thead><tbody>
|
||||
{% for ticket in tickets %}
|
||||
<tr>
|
||||
<td>{{ ticket.customer.customer_profile|default:ticket.customer.username }}</td>
|
||||
<td dir="ltr">{{ ticket.customer.local_mobile }}</td>
|
||||
<td><a href="{% url 'staff_tickets:detail' ticket.public_id %}">{{ ticket.ticket_number }}</a></td>
|
||||
<td>{% if ticket.sms_job %}{% if ticket.sms_job.status == 'SENT' %}پذیرفتهشده توسط درگاه{% else %}{{ ticket.sms_job.get_status_display }}{% endif %}{% if ticket.sms_job.provider_message_id %}<small class="table-subtitle" dir="ltr">مرجع: {{ ticket.sms_job.provider_message_id|truncatechars:45 }}</small>{% endif %}{% if ticket.sms_job.last_error %}<small class="table-subtitle">{{ ticket.sms_job.last_error|truncatechars:60 }}</small>{% endif %}{% else %}ثبت نشده{% endif %}</td><td>{{ ticket.get_status_display }}</td>
|
||||
<td>{% for link in ticket.magic_links.all %}{{ link.view_count }}{% if not forloop.last %} + {% endif %}{% empty %}ارسال نشده{% endfor %}</td>
|
||||
<td>{% if ticket.latest_customer_response %}{{ ticket.latest_customer_response.body|truncatechars:120 }}<small class="table-subtitle">{{ ticket.latest_customer_response.created_at|date:'Y/m/d H:i' }}</small>{% else %}هنوز پاسخی ثبت نشده{% endif %}</td>
|
||||
</tr>
|
||||
{% empty %}<tr><td colspan="7">برای این ارسال تیکتی ثبت نشده است.</td></tr>{% endfor %}
|
||||
</tbody></table></div>
|
||||
</section></div>
|
||||
{% extends 'base.html' %}{% load jalali %}
|
||||
{% block title %}{{ dispatch.subject }}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="operations-page operations-dispatch-detail">
|
||||
<section class="dispatch-report-hero">
|
||||
<div class="dispatch-report-title">
|
||||
<div class="dispatch-title-line"><span class="report-status status-{{ dispatch.status|lower }}">{{ dispatch.get_status_display }}</span><span class="eyebrow">گزارش ارسال گروهی</span></div>
|
||||
<h1>{{ dispatch.subject }}</h1>
|
||||
<div class="dispatch-meta-list">
|
||||
<span><b>واحد</b>{{ dispatch.unit }}</span>
|
||||
<span><b>گروه مخاطبان</b>{{ dispatch.contact_group.name }}</span>
|
||||
<span><b>تعداد گیرندگان</b>{{ dispatch.recipient_count }} نفر</span>
|
||||
<span><b>زمان ایجاد</b><time datetime="{{ dispatch.created_at|date:'c' }}">{{ dispatch.created_at|jalali_datetime }}</time></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dispatch-head-actions">
|
||||
<a class="button" href="{% url 'staff_tickets:dispatch_create' %}">+ ارسال گروهی جدید</a>
|
||||
{% if metrics.failed %}<form method="post" action="{% url 'staff_tickets:dispatch_retry' dispatch.public_id %}">{% csrf_token %}<button class="button button-danger-soft" type="submit">↻ تلاش مجدد {{ metrics.failed }} پیامک</button></form>{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="dispatch-original-message" aria-labelledby="dispatch-message-title">
|
||||
<header><div><span class="panel-index">متن اولیه کارشناس</span><h2 id="dispatch-message-title">پیام اصلی این ارسال</h2></div><span>شناسه عملیات: <b dir="ltr">{{ dispatch.public_id }}</b></span></header>
|
||||
<blockquote>{{ dispatch.body|linebreaksbr }}</blockquote>
|
||||
<footer><span>ایجادکننده: <b>{{ dispatch.created_by.staff_profile.display_name|default:dispatch.created_by.username }}</b></span><span>این متن در یک تیکت مستقل برای هر مخاطب ثبت شده است.</span></footer>
|
||||
</section>
|
||||
|
||||
<section class="delivery-overview" aria-label="خلاصه دلیوری">
|
||||
<div class="delivery-progress-copy"><div><span class="panel-index">پیشرفت تحویل</span><strong>{{ metrics.delivery_percent }}٪</strong></div><p>{{ metrics.delivered }} از {{ dispatch.recipient_count }} پیامک تحویل قطعی شده است.</p></div>
|
||||
<div class="delivery-progress-track" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="{{ metrics.delivery_percent }}"><span style="width:{{ metrics.delivery_percent }}%"></span></div>
|
||||
<div class="delivery-overview-note">{% if metrics.tracking %}<b>{{ metrics.tracking }} پیامک در حال پیگیری است</b><span>نتیجههای موقت هر ۳ دقیقه تا ۴۵ دقیقه دوباره استعلام میشوند.</span>{% elif metrics.failed %}<b>موارد ناموفق نیاز به بررسی دارند</b><span>علت دقیق و دکمه تلاش مجدد در ردیف مخاطب قرار دارد.</span>{% else %}<b>پردازش صف پایان یافته است</b><span>برای جزئیات هر مخاطب، گزارش پایین صفحه را ببینید.</span>{% endif %}</div>
|
||||
</section>
|
||||
|
||||
<section class="dispatch-kpi-grid" aria-label="شاخصهای ارسال گروهی">
|
||||
<article class="dispatch-kpi kpi-success"><span class="kpi-icon">✓</span><div><small>تحویل قطعی</small><strong>{{ metrics.delivered }}</strong><p>رسیده به گوشی</p></div></article>
|
||||
<article class="dispatch-kpi kpi-info"><span class="kpi-icon">◌</span><div><small>پیگیری فعال</small><strong>{{ metrics.tracking }}</strong><p>{{ metrics.sent }} مورد پذیرفتهشده توسط درگاه</p></div></article>
|
||||
<article class="dispatch-kpi kpi-danger"><span class="kpi-icon">!</span><div><small>نیازمند اقدام</small><strong>{{ metrics.failed }}</strong><p>ناموفق یا تحویلنشده قطعی</p></div></article>
|
||||
<article class="dispatch-kpi kpi-view"><span class="kpi-icon">◉</span><div><small>تعامل با لینک</small><strong>{{ metrics.opened }}</strong><p>{{ metrics.total_views }} بازدید · {{ metrics.not_opened }} مخاطب بدون بازدید</p></div></article>
|
||||
<article class="dispatch-kpi kpi-reply"><span class="kpi-icon">↵</span><div><small>پاسخ دریافتی</small><strong>{{ metrics.replied }}</strong><p>پاسخ ثبتشده در تیکتها</p></div></article>
|
||||
</section>
|
||||
|
||||
<section class="ticket-stream dispatch-recipient-report">
|
||||
<header class="stream-head"><div><span class="panel-index">جزئیات هر گیرنده</span><h2>وضعیت پیامک، مشاهده و پاسخ</h2></div><span>{{ dispatch.recipient_count }} مخاطب</span></header>
|
||||
<div class="table-scroll"><table class="dispatch-detail-table"><thead><tr><th>مخاطب</th><th>تیکت</th><th>وضعیت پیامک</th><th>وضعیت تیکت</th><th>مشاهده لینک</th><th>آخرین پاسخ</th></tr></thead><tbody>
|
||||
{% for ticket in tickets %}
|
||||
<tr>
|
||||
<td data-label="مخاطب"><div class="recipient-cell"><span class="recipient-avatar">{{ ticket.customer.customer_profile.first_name|first|default:'•' }}</span><div><strong>{{ ticket.customer.customer_profile|default:ticket.customer.username }}</strong><small dir="ltr">{{ ticket.customer.local_mobile }}</small></div></div></td>
|
||||
<td data-label="تیکت"><a class="ticket-reference" href="{% url 'staff_tickets:detail' ticket.public_id %}"><strong dir="ltr">{{ ticket.ticket_number }}</strong><span>مشاهده تیکت ←</span></a></td>
|
||||
<td data-label="وضعیت پیامک" class="dispatch-sms-state">
|
||||
<div class="sms-state-card tone-{{ ticket.sms_state_tone }}">
|
||||
<span class="sms-state-icon">{% if ticket.sms_state_tone == 'success' %}✓{% elif ticket.sms_state_tone == 'danger' %}!{% elif ticket.sms_state_tone == 'warning' %}◌{% else %}↑{% endif %}</span>
|
||||
<div><strong>{{ ticket.sms_state_title }}</strong><p>{{ ticket.sms_state_hint }}</p>{% if ticket.sms_job.delivery_next_check_at %}<small>استعلام بعدی: {{ ticket.sms_job.delivery_next_check_at|timeuntil }} دیگر</small>{% endif %}</div>
|
||||
</div>
|
||||
{% if ticket.sms_job %}
|
||||
<details class="sms-technical-details">
|
||||
<summary>جزئیات فنی و رهگیری</summary>
|
||||
<dl>
|
||||
<div><dt>ارسال</dt><dd>{% if ticket.sms_job.attempts == 1 %}موفق در اولین تلاش{% else %}{{ ticket.sms_job.attempts }} تلاش از {{ sms_max_attempts }}{% endif %}</dd></div>
|
||||
{% if ticket.sms_job.provider_message_id %}<div><dt>شناسه رهگیری</dt><dd dir="ltr">{{ ticket.sms_job.provider_message_id }}</dd></div>{% endif %}
|
||||
{% if ticket.sms_job.delivery_status_code %}<div><dt>کد دلیوری</dt><dd dir="ltr">{{ ticket.sms_job.delivery_status_code }}</dd></div>{% endif %}
|
||||
{% if ticket.sms_job.delivery_check_attempts %}<div><dt>تعداد استعلام</dt><dd>{{ ticket.sms_job.delivery_check_attempts }} نوبت</dd></div>{% endif %}
|
||||
{% if ticket.sms_job.delivery_checked_at %}<div><dt>آخرین استعلام</dt><dd>{{ ticket.sms_job.delivery_checked_at|jalali_datetime }}</dd></div>{% endif %}
|
||||
</dl>
|
||||
{% if ticket.sms_job.delivery_description %}<p class="gateway-technical-message">{{ ticket.sms_job.delivery_description }}</p>{% endif %}
|
||||
</details>
|
||||
{% if ticket.sms_job.last_error %}<div class="sms-error-panel"><b>علت دقیق عدم ارسال</b><p>{{ ticket.sms_job.last_error }}</p></div>{% endif %}
|
||||
{% if ticket.sms_retryable %}<form method="post" action="{% url 'staff_tickets:dispatch_retry' dispatch.public_id %}" class="inline-retry-form">{% csrf_token %}<input type="hidden" name="job_id" value="{{ ticket.sms_job.pk }}"><button type="submit">↻ تلاش مجدد همین پیامک</button></form>{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td data-label="وضعیت تیکت"><span class="ticket-state-pill state-{{ ticket.status|lower }}">{{ ticket.get_status_display }}</span></td>
|
||||
<td data-label="مشاهده لینک">
|
||||
<div class="engagement-state {% if ticket.magic_total_views %}has-engagement{% endif %}"><span>{% if ticket.magic_total_views %}◉{% else %}○{% endif %}</span><div>{% if ticket.magic_total_views %}<strong>{{ ticket.magic_total_views }} بازدید</strong>{% if ticket.magic_last_used_at %}<small>آخرین بازدید {{ ticket.magic_last_used_at|jalali_datetime }}</small>{% endif %}{% elif ticket.magic_link_count %}<strong>مشاهده نشده</strong><small>{{ ticket.magic_active_count }} لینک فعال</small>{% else %}<strong>لینک صادر نشده</strong>{% endif %}</div></div>
|
||||
</td>
|
||||
<td data-label="آخرین پاسخ">{% if ticket.latest_customer_response %}<div class="recipient-reply"><p>{{ ticket.latest_customer_response.body|truncatechars:140 }}</p><small>{{ ticket.latest_customer_response.created_at|jalali_datetime }}</small></div>{% else %}<span class="no-reply-state">هنوز پاسخی ثبت نشده</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% empty %}<tr><td colspan="6">برای این ارسال تیکتی ثبت نشده است.</td></tr>{% endfor %}
|
||||
</tbody></table></div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in new issue
Block a user