975 lines
49 KiB
HTML
975 lines
49 KiB
HTML
{% load custom_tags %}
|
||
{% load static %}
|
||
{% with url_name=request.resolver_match.url_name %}
|
||
<div id="action" class="column is-12-mobile {% if url_name == 'customerAction' %}is-12-desktop{% else %} is-6-desktop {% endif %}">
|
||
{% endwith %}
|
||
|
||
{% if customer %}
|
||
<div class="box mb-5 has-background-white-ter" style="border: 1px solid #e0e0e0; box-shadow: none; border-radius: 6px;">
|
||
<form method="GET" action="{% url 'admin_panel:customerAction' customer.id %}">
|
||
<div class="columns is-mobile is-multiline is-vcentered m-0">
|
||
|
||
<div class="column is-4-desktop is-12-mobile pb-0">
|
||
<div class="field">
|
||
<label class="label is-small">نوع اقدام</label>
|
||
<div class="control">
|
||
<div class="select is-fullwidth is-small">
|
||
<select name="actionType">
|
||
<option value="all" {% if filter_type == 'all' %}selected{% endif %}>همه موارد</option>
|
||
<option value="bazdid" {% if filter_type == 'bazdid' %}selected{% endif %}>بازدید</option>
|
||
<option value="nasb" {% if filter_type == 'nasb' %}selected{% endif %}>نصب</option>
|
||
<option value="vosol" {% if filter_type == 'vosol' %}selected{% endif %}>وصول مطالبات</option>
|
||
<option value="hamahangi" {% if filter_type == 'hamahangi' %}selected{% endif %}>هماهنگی</option>
|
||
<option value="inCall" {% if filter_type == 'inCall' %}selected{% endif %}>تماس ورودی</option>
|
||
<option value="outCall" {% if filter_type == 'outCall' %}selected{% endif %}>تماس خروجی</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="column is-4-desktop is-12-mobile pb-0">
|
||
<div class="field">
|
||
<label class="label is-small">وضعیت انجام</label>
|
||
<div class="control">
|
||
<div class="select is-fullwidth is-small">
|
||
<select name="status">
|
||
<option value="all" {% if filter_status == 'all' %}selected{% endif %}>همه وضعیتها</option>
|
||
<option value="waite" {% if filter_status == 'waite' %}selected{% endif %}>در انتظار (باز)</option>
|
||
<option value="finish" {% if filter_status == 'finish' %}selected{% endif %}>انجام شده</option>
|
||
<option value="cancell" {% if filter_status == 'cancell' %}selected{% endif %}>لغو شده</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="column is-4-desktop is-12-mobile mt-4 has-text-left pb-0">
|
||
<button type="submit" class="button is-info is-small px-4">اعمال فیلتر</button>
|
||
<a href="{% url 'admin_panel:customerAction' customer.id %}" class="button is-light is-small">حذف فیلتر</a>
|
||
</div>
|
||
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<span id="showActionBox" class="button is-info mb-5">ایجاد وظیفه جدید</span>
|
||
{% endif %}
|
||
|
||
{% if not actions and not actionPr %}
|
||
<div class="notification is-warning is-light has-text-centered">
|
||
هیچ اقدامی با مشخصات انتخابشده یافت نشد!
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% for action in actions %}
|
||
<div customer_id='{{ action.customer.id }}' action_id='{{ action.id }}'
|
||
customer_hold='{% if action.customer.visit_hold_until %}{{ action.customer.visit_hold_until|date:"c" }}{% endif %}'
|
||
class="columns is-mobile is-multiline is-gapless actionBox {{ bgBox }}">
|
||
<div class="column is-12-mobile is-12-desktop actionBoxDesc actionBoxOpenB">
|
||
<div class="pr-4 pl-4 pb-4 pt-4 ax-cardrow">
|
||
<span class="ax-cardrow-main">
|
||
{% ifequal action.status 'finish' %}
|
||
<img class="" style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/check.png' %}">
|
||
{% endifequal %}
|
||
|
||
{% ifequal action.status 'waite' %}
|
||
<img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/time1.png' %}">
|
||
{% endifequal %}
|
||
|
||
{% ifequal action.status 'cancell' %}
|
||
<img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/cancell.png' %}">
|
||
{% endifequal %}
|
||
|
||
<span class="is-bazdid">{% ifequal action.actionType 'nasb' %}نصب{% endifequal %}{% ifequal action.actionType 'bazdid' %}بازدید{% endifequal %}{% ifequal action.actionType 'vosol' %}وصول مطالبات{% endifequal %}{% ifequal action.actionType 'hamahangi' %}هماهنگی{% endifequal %}{% ifequal action.actionType 'inCall' %}تماس ورودی{% endifequal %}{% ifequal action.actionType 'outCall' %}تماس خروجی{% endifequal %}</span>
|
||
<span class="pr-3">{{ action.desc }}</span>
|
||
</span>
|
||
{% if show_delete %}
|
||
{% if action.nazarDT %}
|
||
<span class="ax-del is-locked" title="این اقدام دارای نظرسنجی ثبتشده است و قابل حذف نیست">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm-3 8V6a3 3 0 0 1 6 0v3H9z"/></svg>
|
||
<span class="ax-del-text">نظرسنجی</span>
|
||
</span>
|
||
{% else %}
|
||
<form method="post" class="ax-del-form"
|
||
action="{% url 'admin_panel:customerActionDelete' action.customer.id action.id %}">
|
||
{% csrf_token %}
|
||
<button type="submit" class="ax-del is-danger"
|
||
title="حذف این اقدام"
|
||
data-type="{% ifequal action.actionType 'nasb' %}نصب{% endifequal %}{% ifequal action.actionType 'bazdid' %}بازدید{% endifequal %}{% ifequal action.actionType 'vosol' %}وصول مطالبات{% endifequal %}{% ifequal action.actionType 'hamahangi' %}هماهنگی{% endifequal %}{% ifequal action.actionType 'inCall' %}تماس ورودی{% endifequal %}{% ifequal action.actionType 'outCall' %}تماس خروجی{% endifequal %}"
|
||
onclick="return confirm('این «' + (this.dataset.type || 'اقدام') + '» حذف شود؟\n\nاقدام از فهرست انتظار/وظایف خارج میشود و پیامک ارسالنشدهٔ مرتبط لغو میگردد. سابقه برای حسابرسی باقی میماند.');">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 3h6l1 2h4v2H4V5h4l1-2zm-3 6h12l-1 12a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2L6 9zm4 3v8h2v-8h-2zm4 0v8h2v-8h-2z"/></svg>
|
||
<span class="ax-del-text">حذف</span>
|
||
</button>
|
||
</form>
|
||
{% endif %}
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="column is-12-mobile is-12-desktop actionBoxOpenB">
|
||
<div class="pr-4 pl-4 pb-4 pt-4 actionBoxBorder">
|
||
<span class="is-result">نتیجه</span>
|
||
<span>{% if action.result %} {{ action.result }} {% else %}هنوز گزارش یا نتیجه ای ثبت نشده!{% endif %}</span>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="column is-4-mobile is-4-desktop">
|
||
<div class="has-text-centered p-3">
|
||
<span class="ss02">{{ action.actionDateTime | toJalali }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="column is-8-mobile is-4-desktop">
|
||
<div class="has-text-centered actionBoxFtBox p-3">
|
||
<a href="{% url 'admin_panel:customerNew' action.customer.id %}">
|
||
<span>{{ action.customer.name_family }}</span>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<div class="column is-12-mobile is-4-desktop is-hidden-mobile">
|
||
<div class="has-text-centered p-3">
|
||
<span>{{ action.forUser.first_name }} {{ action.forUser.last_name }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
|
||
{% if actionPr %}
|
||
<hr>
|
||
<p style="text-align: center; margin-bottom: 20px; color: #d90000; font-size: 18px;"> کارهای مانده از روزهای قبل</p>
|
||
|
||
{% for action in actionPr %}
|
||
<div customer_id='{{ action.customer.id }}' action_id='{{ action.id }}'
|
||
customer_hold='{% if action.customer.visit_hold_until %}{{ action.customer.visit_hold_until|date:"c" }}{% endif %}'
|
||
class="columns is-mobile is-multiline is-gapless actionBox {{ bgBox }}">
|
||
<div class="column is-12-mobile is-12-desktop actionBoxDesc actionBoxOpenB">
|
||
<div class="pr-4 pl-4 pb-4 pt-4">
|
||
{% ifequal action.status 'finish' %}
|
||
<img class="" style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/check.png' %}">
|
||
{% endifequal %}
|
||
|
||
{% ifequal action.status 'waite' %}
|
||
<img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/time1.png' %}">
|
||
{% endifequal %}
|
||
|
||
{% ifequal action.status 'cancell' %}
|
||
<img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/cancell.png' %}">
|
||
{% endifequal %}
|
||
|
||
<span class="is-bazdid">{% ifequal action.actionType 'nasb' %}نصب{% endifequal %}{% ifequal action.actionType 'bazdid' %}بازدید{% endifequal %}{% ifequal action.actionType 'vosol' %}وصول مطالبات{% endifequal %}{% ifequal action.actionType 'hamahangi' %}هماهنگی{% endifequal %}{% ifequal action.actionType 'inCall' %}تماس ورودی{% endifequal %}{% ifequal action.actionType 'outCall' %}تماس خروجی{% endifequal %}</span>
|
||
<span class="pr-3">{{ action.desc }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="column is-12-mobile is-12-desktop actionBoxOpenB">
|
||
<div class="pr-4 pl-4 pb-4 pt-4 actionBoxBorder">
|
||
<span class="is-result">نتیجه</span>
|
||
<span>{% if action.result %} {{ action.result }} {% else %}هنوز گزارش یا نتیجه ای ثبت نشده!{% endif %}</span>
|
||
</div>
|
||
</div>
|
||
<div class="column is-4-mobile is-4-desktop">
|
||
<div class="has-text-centered p-3">
|
||
<span class="ss02">{{ action.actionDateTime | toJalali }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="column is-8-mobile is-4-desktop">
|
||
<div class="has-text-centered actionBoxFtBox p-3">
|
||
<a href="{% url 'admin_panel:customerNew' action.customer.id %}">
|
||
<span>{{ action.customer.name_family }}</span>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<div class="column is-12-mobile is-4-desktop is-hidden-mobile">
|
||
<div class="has-text-centered p-3">
|
||
<span>{{ action.forUser.first_name }} {{ action.forUser.last_name }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
{% endif %}
|
||
|
||
</div>
|
||
|
||
<style>
|
||
/* ===== دکمهٔ «حذف» روی کارت اقدام (mobile first) ===== */
|
||
.ax-cardrow {
|
||
display: flex; align-items: flex-start; justify-content: space-between;
|
||
gap: .5rem; flex-wrap: nowrap;
|
||
}
|
||
.ax-cardrow-main { flex: 1 1 auto; min-width: 0; }
|
||
.ax-del-form { margin: 0; flex: 0 0 auto; }
|
||
.ax-del {
|
||
display: inline-flex; align-items: center; gap: .25rem;
|
||
padding: .2rem .45rem; border-radius: .375rem; border: 1px solid #e5e7eb;
|
||
background: #fff; color: #6b7280; font-size: .68rem; font-weight: 700;
|
||
cursor: pointer; line-height: 1.5; white-space: nowrap;
|
||
transition: background-color .15s ease, border-color .15s ease,
|
||
color .15s ease, box-shadow .15s ease;
|
||
}
|
||
.ax-del svg { width: 13px; height: 13px; fill: currentColor; flex: 0 0 auto; }
|
||
.ax-del:hover { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }
|
||
.ax-del:focus-visible {
|
||
outline: 2px solid #fca5a5; outline-offset: 1px;
|
||
}
|
||
.ax-del.is-danger { border-color: #fee2e2; color: #dc2626; background: #fff; }
|
||
.ax-del.is-danger:hover {
|
||
background: #dc2626; border-color: #dc2626; color: #fff;
|
||
box-shadow: 0 1px 6px rgba(220, 38, 38, .25);
|
||
}
|
||
/* «نظرسنجی دارد» ⇒ دکمه غیرفعال (قاعدهٔ محصولی) */
|
||
.ax-del.is-locked {
|
||
cursor: not-allowed; color: #9ca3af; background: #f9fafb;
|
||
border-color: #e5e7eb;
|
||
}
|
||
.ax-del.is-locked:hover { background: #f9fafb; border-color: #e5e7eb; color: #9ca3af; }
|
||
@media (max-width: 480px) {
|
||
.ax-del-text { display: none; } /* در موبایل فقط آیکون، برای صرفهجویی فضا */
|
||
.ax-del { padding: .25rem; }
|
||
}
|
||
|
||
/* ===== مودال «ایجاد/ویرایش وظیفه» — mobile first =====
|
||
همهٔ کلاسها با پیشوند ax- هستند تا با سایر بخشها تداخل نکنند. */
|
||
#ActionBox .ax-card {
|
||
width: calc(100% - 1rem); max-width: 44rem;
|
||
max-height: calc(100vh - 1rem); display: flex; flex-direction: column;
|
||
border-radius: .75rem; overflow: hidden;
|
||
}
|
||
#ActionBox .ax-head {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
gap: .5rem; padding: .75rem 1rem; flex: 0 0 auto;
|
||
background: #f8fafc; border-bottom: 1px solid #e5e7eb;
|
||
}
|
||
#ActionBox .ax-title { font-size: .95rem; font-weight: 800; color: #0f172a; margin: 0; }
|
||
#ActionBox .ax-sub { font-size: .75rem; color: #64748b; margin: .1rem 0 0; }
|
||
#ActionBox .ax-body {
|
||
padding: .75rem 1rem; overflow-y: auto; -webkit-overflow-scrolling: touch;
|
||
flex: 1 1 auto;
|
||
}
|
||
#ActionBox .ax-foot {
|
||
display: flex; gap: .5rem; justify-content: flex-start;
|
||
padding: .6rem 1rem; flex: 0 0 auto;
|
||
background: #f8fafc; border-top: 1px solid #e5e7eb;
|
||
}
|
||
#ActionBox .ax-foot .button { margin: 0 !important; min-height: 2.6rem; flex: 1 1 0; }
|
||
@media (min-width: 768px) {
|
||
#ActionBox .ax-foot { justify-content: flex-start; }
|
||
#ActionBox .ax-foot .button { flex: 0 0 auto; min-width: 7rem; }
|
||
}
|
||
|
||
/* بخشها */
|
||
#ActionBox .ax-section { padding: .6rem 0; border-bottom: 1px dashed #eef2f6; }
|
||
#ActionBox .ax-section:last-of-type { border-bottom: 0; }
|
||
#ActionBox .ax-legend {
|
||
display: flex; align-items: center; gap: .4rem;
|
||
font-size: .78rem; font-weight: 800; color: #0e7490; margin: 0 0 .5rem;
|
||
}
|
||
#ActionBox .ax-step {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
width: 1.35rem; height: 1.35rem; border-radius: 999px;
|
||
background: #33b5d3; color: #fff; font-size: .7rem; font-weight: 800;
|
||
}
|
||
|
||
/* شبکهٔ فیلدها: موبایل تکستونه، دسکتاپ دوستونه */
|
||
#ActionBox .ax-grid { display: grid; grid-template-columns: 1fr; gap: .6rem; }
|
||
@media (min-width: 768px) {
|
||
#ActionBox .ax-grid { grid-template-columns: 1fr 1fr; }
|
||
#ActionBox .ax-span-2 { grid-column: 1 / -1; }
|
||
}
|
||
#ActionBox .ax-label {
|
||
font-size: .74rem !important; font-weight: 700; color: #475569; margin-bottom: .25rem;
|
||
}
|
||
#ActionBox .ax-help {
|
||
font-size: .7rem; color: #94a3b8; margin-top: .2rem; line-height: 1.5;
|
||
}
|
||
/* هدف لمسی بزرگتر روی موبایل */
|
||
#ActionBox .input, #ActionBox .select select, #ActionBox .textarea {
|
||
font-size: .85rem;
|
||
}
|
||
@media (max-width: 767px) {
|
||
#ActionBox .input, #ActionBox .select select { min-height: 2.6rem; }
|
||
#ActionBox .textarea { min-height: 4.5rem; }
|
||
}
|
||
#ActionBox .select, #ActionBox .select select { width: 100%; }
|
||
|
||
/* ردیف تیک «انجام شده» */
|
||
#ActionBox .ax-check {
|
||
display: flex; align-items: center; gap: .5rem;
|
||
padding: .55rem .7rem; border: 1px solid #e5e7eb; border-radius: .5rem;
|
||
background: #fff; cursor: pointer; margin: 0;
|
||
}
|
||
#ActionBox .ax-check input { width: 1.05rem; height: 1.05rem; }
|
||
|
||
/* هشدار «آیا هماهنگی را انجام دادی؟» — فقط برای هماهنگیِ تیکخورده */
|
||
#ActionBox .ax-warn {
|
||
margin-top: .5rem; padding: .6rem .7rem;
|
||
border: 1px solid #fcd34d; border-radius: .5rem; background: #fffbeb;
|
||
color: #92400e; font-size: .78rem; line-height: 1.75;
|
||
}
|
||
#ActionBox .ax-warn .ax-warn-q { font-weight: 800; color: #78350f; margin: 0 0 .15rem; }
|
||
#ActionBox .ax-warn .ax-warn-hint { margin: 0; }
|
||
#ActionBox .ax-warn .ax-warn-actions {
|
||
display: none; gap: .4rem; margin-top: .55rem; flex-wrap: wrap;
|
||
}
|
||
#ActionBox .ax-warn .ax-warn-actions .button { margin: 0 !important; flex: 1 1 auto; }
|
||
@media (min-width: 768px) {
|
||
#ActionBox .ax-warn .ax-warn-actions .button { flex: 0 0 auto; }
|
||
}
|
||
/* وقتی ارسال متوقف شده تا کاربر تأیید کند */
|
||
#ActionBox .ax-warn.is-confirming {
|
||
border-color: #f59e0b; box-shadow: 0 0 0 3px #fde68a66; background: #fef3c7;
|
||
}
|
||
#ActionBox .ax-warn.is-confirming .ax-warn-actions { display: flex; }
|
||
#ActionBox .ax-warn:focus { outline: 2px solid #f59e0b; outline-offset: 2px; }
|
||
|
||
/* اعلان «تاریخ قرار عقبتر» — کلاس مستقل تا به CSS پنل «انجام شد» وابسته نباشد */
|
||
#ActionBox .ax-holdback {
|
||
margin-top: .5rem; padding: .6rem .7rem;
|
||
border: 1px solid #fcd34d; border-radius: .5rem; background: #fffbeb;
|
||
color: #92400e; font-size: .78rem; line-height: 1.75;
|
||
}
|
||
#ActionBox .ax-holdback.is-blocking {
|
||
border-color: #f59e0b; box-shadow: 0 0 0 3px #fde68a66; background: #fef3c7;
|
||
}
|
||
#ActionBox .ax-holdback .ax-hb-title { font-weight: 800; color: #78350f; margin: 0 0 .15rem; }
|
||
#ActionBox .ax-holdback .ax-hb-current { margin: 0 0 .4rem; }
|
||
#ActionBox .ax-holdback .ax-hb-current b { font-weight: 800; }
|
||
#ActionBox .ax-holdback .ax-hb-alt { margin: 0; }
|
||
#ActionBox .ax-holdback .ax-hb-check {
|
||
display: flex; align-items: flex-start; gap: .5rem; margin: 0;
|
||
padding: .5rem .6rem; border-radius: .45rem; background: #fff;
|
||
border: 1px solid #fbbf24; cursor: pointer; font-weight: 700; color: #7c2d12;
|
||
}
|
||
#ActionBox .ax-holdback .ax-hb-check input {
|
||
width: 1.05rem; height: 1.05rem; margin-top: .15rem; flex: 0 0 auto;
|
||
}
|
||
#ActionBox .ax-holdback:focus { outline: 2px solid #f59e0b; outline-offset: 2px; }
|
||
|
||
#ActionBox .ax-help-toggle {
|
||
display: flex; align-items: center; gap: .45rem; width: 100%;
|
||
padding: .55rem .7rem; border: 1px solid #bae6fd; border-radius: .5rem;
|
||
background: #f0f9ff; color: #0369a1; font-size: .78rem; font-weight: 700;
|
||
cursor: pointer; text-align: right; line-height: 1.4;
|
||
}
|
||
#ActionBox .ax-help-toggle:hover { background: #e0f2fe; }
|
||
#ActionBox .ax-help-toggle .ax-ico {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
width: 1.25rem; height: 1.25rem; border-radius: 999px; flex: 0 0 auto;
|
||
background: #0284c7; color: #fff; font-size: .72rem; font-weight: 800;
|
||
}
|
||
#ActionBox .ax-help-toggle .ax-chev {
|
||
margin-inline-start: auto; transition: transform .15s ease; font-size: .8rem;
|
||
}
|
||
#ActionBox .ax-help-toggle[aria-expanded="true"] .ax-chev { transform: rotate(180deg); }
|
||
#ActionBox .ax-help-panel {
|
||
margin-top: .4rem; padding: .7rem .8rem; border: 1px solid #e0f2fe;
|
||
border-radius: .5rem; background: #fbfeff; font-size: .76rem; color: #334155;
|
||
line-height: 1.85;
|
||
}
|
||
#ActionBox .ax-help-panel h4 {
|
||
font-size: .78rem; font-weight: 800; color: #0f172a; margin: .6rem 0 .25rem;
|
||
}
|
||
#ActionBox .ax-help-panel h4:first-child { margin-top: 0; }
|
||
#ActionBox .ax-help-panel ul { margin: 0; padding-inline-start: 1.1rem; }
|
||
#ActionBox .ax-help-panel li { margin-bottom: .2rem; }
|
||
#ActionBox .ax-help-panel .ax-eg {
|
||
display: block; margin-top: .35rem; padding: .5rem .6rem;
|
||
background: #fff; border: 1px dashed #bae6fd; border-radius: .4rem;
|
||
}
|
||
</style>
|
||
|
||
{% if customer %}
|
||
<form id="ActionBox" class="modal" method="post" action="{% url 'admin_panel:customerNewAction' customer.id %}"
|
||
data-customer-hold="{% if customer.visit_hold_until %}{{ customer.visit_hold_until|date:'c' }}{% endif %}">
|
||
{% else %}
|
||
<form id="ActionBox" class="modal" method="post" action="">
|
||
{% endif %}
|
||
|
||
{% csrf_token %}
|
||
{# تأیید صریح کاربر برای عقببردن تاریخ قرار؛ فقط با زدن دکمهٔ تأیید پر میشود. #}
|
||
<input type="hidden" name="force_hold" id="forceHold" value="">
|
||
<div class="modal-background closeActionBox"></div>
|
||
<div class="modal-card ax-card">
|
||
<header class="modal-card-head ax-head">
|
||
<div>
|
||
<p class="ax-title">ایجاد وظیفه</p>
|
||
{% if customer %}<p class="ax-sub">{{ customer.name_family }}</p>{% endif %}
|
||
</div>
|
||
<button type="button" class="delete closeActionBox" aria-label="بستن"></button>
|
||
</header>
|
||
<section class="modal-card-body ax-body">
|
||
|
||
{# ---------- گام ۱: نوع اقدام و مسئول ---------- #}
|
||
<div class="ax-section">
|
||
<p class="ax-legend"><span class="ax-step">۱</span> نوع اقدام و مسئول</p>
|
||
<div class="ax-grid">
|
||
<div class="ax-field">
|
||
<label class="label ax-label" for="actionType">نوع اقدام</label>
|
||
<div class="select">
|
||
<select id="actionType" required name="actionType">
|
||
<option value="">انتخاب کنید</option>
|
||
<option value="bazdid">بازدید</option>
|
||
<option value="nasb">نصب</option>
|
||
<option value="vosol">وصول مطالبات</option>
|
||
<option value="hamahangi">هماهنگی</option>
|
||
<option value="inCall">تماس ورودی</option>
|
||
<option value="outCall">تماس خروجی</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="ax-field">
|
||
<label class="label ax-label" for="userID">توسط</label>
|
||
<div class="select">
|
||
<select id="userID" required name="userID">
|
||
<option value="">انتخاب کنید</option>
|
||
{% if perms.admin_panel.ViewStore %}
|
||
{% for auser in allUsers %}
|
||
<option value="{{ auser.id }}">{{ auser.first_name }} {{ auser.last_name }}</option>
|
||
{% endfor %}
|
||
{% else %}
|
||
<option value="{{ request.user.id }}">{{ request.user.first_name }} {{ request.user.last_name }}</option>
|
||
<option value="6">خدمات پس از فروش</option>
|
||
{% endif %}
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{# ---------- گام ۲: زمانبندی ---------- #}
|
||
<div class="ax-section">
|
||
<p class="ax-legend"><span class="ax-step">۲</span> زمانبندی</p>
|
||
<div class="ax-grid">
|
||
<div class="ax-field">
|
||
<label class="label ax-label">تاریخ و ساعتی که کار باید انجام شود</label>
|
||
<input type="text" class="input dateTimePickerAnjam" autocomplete="off">
|
||
<input id="dateTimeAnjam" name="dateTimeAnjam" required type="text" class="input is-hidden dateTimePickerAnjam-alt">
|
||
<p class="ax-help">تاریخ انجام این وظیفه (ثبت در «لیست وظایف» همان روز).</p>
|
||
</div>
|
||
|
||
{# فیلد «تا تاریخ پیگیری نشود» فقط برای «هماهنگی» #}
|
||
<div class="ax-field showWhenCoordination is-hidden">
|
||
<label class="label ax-label">تا تاریخ پیگیری نشود</label>
|
||
<input type="text" class="input dateTimePickerHoldUntil" autocomplete="off">
|
||
<input name="visitHoldUntil" id="visitHoldUntil" type="text" class="input is-hidden dateTimePickerHoldUntil-alt">
|
||
<p class="ax-help">تا پایان این روز، مشتری در «انتظار بازدید» دیده نمیشود. خالی = ۱۴ روز.</p>
|
||
</div>
|
||
</div>
|
||
|
||
{# اعلان «تاریخ عقبتر» — عرض کامل، بیرون از شبکهٔ دوستونه #}
|
||
<div class="ax-holdback is-hidden" id="holdBackwardNotice" tabindex="-1"
|
||
role="alert" aria-live="polite">
|
||
<p class="ax-hb-title">این تاریخ از قرار فعلی عقبتر است</p>
|
||
<p class="ax-hb-current">قرار فعلی: <b id="hbCurrent">—</b></p>
|
||
<label class="ax-hb-check is-hidden" id="hbForceRow" for="forceHoldCheck">
|
||
<input type="checkbox" id="forceHoldCheck">
|
||
<span>تاریخ قرار را عقب ببر</span>
|
||
</label>
|
||
<p class="ax-hb-alt is-hidden" id="hbCreateHint">
|
||
این تاریخ ذخیره نمیشود. برای تغییر قرار، وظیفهٔ هماهنگی فعلی را ویرایش کنید.
|
||
</p>
|
||
</div>
|
||
|
||
{# راهنمای بازشونده — فقط برای هماهنگی #}
|
||
<div class="ax-help-wrap showWhenCoordination is-hidden" style="margin-top: .6rem;">
|
||
<button type="button" class="ax-help-toggle" id="holdHelpToggle"
|
||
aria-expanded="false" aria-controls="holdHelpPanel">
|
||
<span class="ax-ico" aria-hidden="true">!</span>
|
||
<span>راهنمای «هماهنگی» و «تا تاریخ پیگیری نشود»</span>
|
||
<span class="ax-chev" aria-hidden="true">▾</span>
|
||
</button>
|
||
<div class="ax-help-panel is-hidden" id="holdHelpPanel">
|
||
<h4>این تاریخ چه کاری میکند؟</h4>
|
||
<p>میگوید «تا این تاریخ با این مشتری تماس نگیرید». در این بازه، مشتری از فهرست
|
||
<span class="has-text-weight-bold">انتظار بازدید</span> پنهان میشود و روز بعد از آن
|
||
تاریخ <span class="has-text-weight-bold">خودکار</span> برمیگردد. تاریخ تا
|
||
<span class="has-text-weight-bold">پایان همان روز</span> معتبر است.</p>
|
||
|
||
<h4>مثال</h4>
|
||
<div class="ax-eg">
|
||
امروز ۱ آذر است. مشتری میگوید «سه هفتهٔ دیگر زنگ بزنید».<br>
|
||
نوع = <b>هماهنگی</b> ← تیک «این کار انجام شده» ← «تا تاریخ پیگیری نشود» = <b>۲۲ آذر</b>.<br>
|
||
نتیجه: از ۱ تا ۲۲ آذر مشتری در فهرست نیست؛ از ۲۳ آذر خودکار برمیگردد.
|
||
</div>
|
||
|
||
<h4>نکات مهم</h4>
|
||
<ul>
|
||
<li><b>خالی + تیک</b> ← سیستم خودش ۱۴ روز میگذارد.</li>
|
||
<li><b>خالی + بدون تیک</b> ← هیچ تعویقی ثبت نمیشود؛ مشتری در فهرست میماند.</li>
|
||
<li><b>فقط تمدید میکند، کوتاه نمیکند:</b> اگر قرار ۲۲ آذر باشد و همکار دیگری ۳۰ آذر بگذارد،
|
||
قرار به ۳۰ آذر میرود؛ تاریخهای عقبتر نادیده گرفته میشوند تا قرارِ دورتر از بین نرود.
|
||
اگر خودتان میخواهید قرار را عقب ببرید، وظیفه را <b>ویرایش</b> کنید و
|
||
گزینهٔ <b>«تاریخ قرار را عقب ببر»</b> را تیک بزنید
|
||
(در «ایجاد وظیفهٔ تازه» این گزینه وجود ندارد).</li>
|
||
<li><b>حذف یا لغو هماهنگی</b> ← قرار بیاثر میشود و مشتری بلافاصله برمیگردد.</li>
|
||
<li><b>سقف ۶ ماه</b> است؛ بیشتر از آن با پیام خطا رد میشود.</li>
|
||
<li>این فیلد <b>تاریخ بازدید پرسنل نیست</b> و <b>بازدید حساب نمیشود</b>؛
|
||
تاریخ آخرین بازدید و دورهٔ ۹ ماههٔ پیامک دست نمیخورد.
|
||
برای اعزام پرسنل از اقدام نوع <b>بازدید</b> استفاده کنید.</li>
|
||
<li>در مدت تعویق، <b>پیامک یادآوری ۹ ماههٔ بازدید</b> ارسال نمیشود.</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{# ---------- گام ۳: توضیحات ---------- #}
|
||
<div class="ax-section">
|
||
<p class="ax-legend"><span class="ax-step">۳</span> توضیحات و وضعیت</p>
|
||
<div class="ax-grid">
|
||
<div class="ax-field ax-span-2">
|
||
<label class="label ax-label" for="desc">توضیحات برای یادآوری حین انجام کار</label>
|
||
<textarea id="desc" required name="desc" class="textarea"
|
||
placeholder="مثلا: با مشتری تماس بگیرم برای هماهنگی تعویض فیلتر دستگاه"></textarea>
|
||
</div>
|
||
|
||
<div class="ax-field ax-span-2">
|
||
<label class="ax-check">
|
||
<input name="is_done" id="checkIsDone" type="checkbox">
|
||
<span>این کار انجام شده است</span>
|
||
</label>
|
||
|
||
{# هشدار/تأیید: فقط برای «هماهنگی» با تیکِ «انجام شده» #}
|
||
<div class="ax-warn is-hidden" id="holdDoneWarning" tabindex="-1"
|
||
role="alert" aria-live="polite">
|
||
<p class="ax-warn-q">آیا مطمئن هستی که هماهنگی را انجام دادی؟</p>
|
||
<p class="ax-warn-hint">اگر هنوز هماهنگی نکردی، این تیک را بردار.</p>
|
||
<div class="ax-warn-actions">
|
||
<button type="button" id="holdConfirmYes" class="button is-warning is-small">
|
||
بله، هماهنگی انجام شد
|
||
</button>
|
||
<button type="button" id="holdConfirmNo" class="button is-light is-small">
|
||
نه، تیک را بردار
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="ax-field showWhenDone is-hidden">
|
||
<label class="label ax-label" for="FinishDateTime">تاریخ و ساعت اتمام کار</label>
|
||
<input id="FinishDateTime" type="text" class="input dateTimePickerFinish" autocomplete="off">
|
||
<input name="FinishDateTime" type="text" class="input dateTimePickerFinish-alt is-hidden">
|
||
<p class="ax-help">خالی بماند، زمان ثبت در نظر گرفته میشود.</p>
|
||
</div>
|
||
|
||
<div class="ax-field showWhenDone is-hidden">
|
||
<label class="label ax-label" for="actionResult">نتیجه</label>
|
||
<textarea name="result" id="actionResult" class="textarea"
|
||
placeholder="نتیجهٔ کار یا پیگیری انجامشده را بنویسید"></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
<footer class="modal-card-foot ax-foot">
|
||
<button type="button" class="button closeActionBox">انصراف</button>
|
||
<input id="sabtBtn05" type="submit" class="button is-success" value="ثبت"/>
|
||
</footer>
|
||
</div>
|
||
</form>
|
||
|
||
<script>
|
||
// وضعیت مودال:
|
||
// isEditMode ⇒ در حال ویرایش یک اقدام موجود (نه ایجاد)
|
||
// holdAutoChecked ⇒ تیک «انجام شده» را خودِ سیستم برای هماهنگی زده است
|
||
// holdConfirmed ⇒ کاربر تأیید کرده که هماهنگی انجام شده است
|
||
var isEditMode = false;
|
||
var holdAutoChecked = false;
|
||
var holdConfirmed = false;
|
||
|
||
// لایهٔ دوم محافظت: فرم «حذف» داخل کارتِ قابلکلیک است؛ رویداد را همانجا
|
||
// متوقف میکنیم تا به هندلرِ بازکردن مودالِ ویرایش نرسد.
|
||
// بایند «مستقیم» (نه delegated) چون این بلوک با هر ردیف تکرار میشود؛
|
||
// نامفضا (axdel) + off مانع از انباشتهشدن هندلرها روی ردیفهای تکراری میشود.
|
||
$('.ax-del-form, .ax-del')
|
||
.off('.axdel')
|
||
.on('click.axdel mousedown.axdel', function (e) {
|
||
e.stopPropagation();
|
||
});
|
||
|
||
// پیکر «تا تاریخ پیگیری نشود» را ریست میکند.
|
||
// نکته: pDatepicker یک Model برمیگرداند؛ اگر سلکتور هیچ المانی پیدا نکند
|
||
// مقدار undefined میشود. بدون این محافظ، یک ناهمخوانی نام کلاس باعث
|
||
// TypeError میشد و بقیهٔ منطقِ هندلر (پنهانکردن فیلدها، برداشتن تیک خودکار)
|
||
// اجرا نمیشد.
|
||
// پرکردن پیکر «تا تاریخ پیگیری نشود» از مقدار ذخیرهشدهٔ مشتری.
|
||
// بدون این، هنگام بازکردن مجدد یک اقدام، فیلد همیشه خالی دیده میشد
|
||
// (مقدار در دیتابیس بود ولی مودال آن را بارگذاری نمیکرد).
|
||
function seedHoldPicker(isoValue) {
|
||
var box = $("#visitHoldUntil");
|
||
if (!isoValue) {
|
||
resetHoldPicker();
|
||
return;
|
||
}
|
||
var ms = new Date(isoValue).getTime();
|
||
if (isNaN(ms)) {
|
||
resetHoldPicker();
|
||
return;
|
||
}
|
||
if (dateTimePickerHoldUntil && typeof dateTimePickerHoldUntil.setDate === 'function') {
|
||
dateTimePickerHoldUntil.setDate(ms);
|
||
}
|
||
box.val(String(ms));
|
||
}
|
||
|
||
function resetHoldPicker() {
|
||
if (dateTimePickerHoldUntil && typeof dateTimePickerHoldUntil.setDate === 'function') {
|
||
dateTimePickerHoldUntil.setDate();
|
||
}
|
||
$("#visitHoldUntil").val('');
|
||
}
|
||
|
||
$(".closeActionBox").click(function(){
|
||
$("#ActionBox").removeClass("is-active");
|
||
});
|
||
|
||
$("#showActionBox").click(function(){
|
||
isEditMode = false;
|
||
holdAutoChecked = false;
|
||
holdConfirmed = false;
|
||
$("#holdDoneWarning").addClass("is-hidden").removeClass("is-confirming");
|
||
$("#ActionBox").addClass("is-active");
|
||
{% if customer %}
|
||
var NewActionUrl = "{% url 'admin_panel:customerNewAction' customer.id %}";
|
||
$("#ActionBox").prop("action", NewActionUrl);
|
||
{% endif %}
|
||
$("#actionType").val('');
|
||
$("#desc").val('');
|
||
$("#userID").val('');
|
||
$("#checkIsDone").prop('checked', false);
|
||
$(".showWhenDone").addClass("is-hidden");
|
||
$("#actionResult").val('');
|
||
dateTimePickerAnjam.setDate();
|
||
dateTimePickerFinish.setDate();
|
||
resetHoldPicker();
|
||
syncHoldBackward();
|
||
$(".showWhenCoordination").addClass("is-hidden");
|
||
closeHoldHelp();
|
||
$("#sabtBtn05").val("ثبت");
|
||
});
|
||
|
||
// نمایش/پنهانکردن فیلدهای «انجام شده».
|
||
function syncDoneFields() {
|
||
$(".showWhenDone").toggleClass("is-hidden", !$("#checkIsDone").prop("checked"));
|
||
}
|
||
|
||
// هشدار «آیا هماهنگی را انجام دادی؟» فقط برای هماهنگیِ تیکخورده نمایش داده میشود.
|
||
function syncHoldWarning() {
|
||
var active = ($("#actionType").val() === 'hamahangi') && $("#checkIsDone").prop("checked");
|
||
$("#holdDoneWarning").toggleClass("is-hidden", !active);
|
||
if (!active) {
|
||
$("#holdDoneWarning").removeClass("is-confirming");
|
||
holdConfirmed = false;
|
||
}
|
||
}
|
||
|
||
$("#checkIsDone").change(function() {
|
||
// تغییر دستی کاربر ⇒ دیگر «تیک خودکار» نیست.
|
||
holdAutoChecked = false;
|
||
holdConfirmed = false;
|
||
syncDoneFields();
|
||
syncHoldWarning();
|
||
});
|
||
|
||
// تأیید یا ردِ هشدار در لحظهٔ ثبت
|
||
function showHoldConfirm() {
|
||
var box = $("#holdDoneWarning");
|
||
box.removeClass("is-hidden").addClass("is-confirming");
|
||
if (box[0].scrollIntoView) {
|
||
box[0].scrollIntoView({ block: 'center', behavior: 'smooth' });
|
||
}
|
||
box.trigger('focus');
|
||
}
|
||
|
||
$("#holdConfirmYes").click(function() {
|
||
holdConfirmed = true;
|
||
// submit مستقیم روی المان فرم؛ اعتبارسنجی HTML5 در تلاش اول انجام شده است.
|
||
$("#ActionBox")[0].submit();
|
||
});
|
||
|
||
$("#holdConfirmNo").click(function() {
|
||
holdConfirmed = false;
|
||
holdAutoChecked = false;
|
||
$("#checkIsDone").prop("checked", false);
|
||
$("#holdDoneWarning").addClass("is-hidden").removeClass("is-confirming");
|
||
syncDoneFields();
|
||
$("#checkIsDone").trigger('focus');
|
||
});
|
||
|
||
// ══════════ عقببردن تاریخ قرار ══════════
|
||
// قاعدهٔ سیستم: تاریخ «تا تاریخ پیگیری نشود» فقط رو به جلو میرود تا قرارِ
|
||
// دورتری که ثبت شده از بین نرود. در «ویرایش» اگر کاربر خودش بخواهد عقب ببرد،
|
||
// قرار فعلی را میبیند و با تیک زدن اجازهٔ صریح میدهد. در «ایجادِ» وظیفهٔ تازه
|
||
// این اجازه داده نمیشود؛ چون کاربر قصد اصلاح قرارِ موجود را ندارد و ممکن است
|
||
// ناخواسته قولِ ثبتشدهٔ قبلی را کوتاه کند.
|
||
|
||
function holdCurrentMs() {
|
||
var iso = ($("#ActionBox").attr('data-customer-hold') || '').trim();
|
||
if (!iso) { return null; }
|
||
var ms = new Date(iso).getTime();
|
||
return isNaN(ms) ? null : ms;
|
||
}
|
||
|
||
// مقدار پیکر در فیلد مخفی بهصورت timestamp میلیثانیهای است؛ اگر پیکر
|
||
// تاریخ شمسی متنی گذاشت، همان را هم میپذیریم.
|
||
function holdTargetMs() {
|
||
var raw = ($("#visitHoldUntil").val() || '').trim();
|
||
if (!raw) { return null; }
|
||
if (/^\d+$/.test(raw)) {
|
||
var n = parseInt(raw, 10);
|
||
return isNaN(n) ? null : n;
|
||
}
|
||
var parsed = Date.parse(raw.replace(/\//g, '-'));
|
||
return isNaN(parsed) ? null : parsed;
|
||
}
|
||
|
||
function sameLocalDay(a, b) {
|
||
var da = new Date(a), db = new Date(b);
|
||
return da.getFullYear() === db.getFullYear()
|
||
&& da.getMonth() === db.getMonth()
|
||
&& da.getDate() === db.getDate();
|
||
}
|
||
|
||
function jalaliDay(ms) {
|
||
if (ms === null) { return '—'; }
|
||
try {
|
||
if (typeof persianDate !== 'undefined') {
|
||
return new persianDate(ms).format('YYYY/MM/DD');
|
||
}
|
||
} catch (err) { /* کتابخانه در دسترس نیست ⇒ تاریخ میلادی */ }
|
||
var d = new Date(ms);
|
||
return d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate();
|
||
}
|
||
|
||
// آیا تاریخ انتخابی از قرار فعلی عقبتر است؟ (مستقل از تیک کاربر)
|
||
function holdIsBackward() {
|
||
if ($("#actionType").val() !== 'hamahangi') { return false; }
|
||
var current = holdCurrentMs(), target = holdTargetMs();
|
||
if (current === null || target === null) { return false; }
|
||
if (sameLocalDay(current, target)) { return false; }
|
||
return target < current;
|
||
}
|
||
|
||
// بهروزرسانی اعلان (و اجازهٔ عقببردن فقط در ویرایش) — با هر تغییر تاریخ/نوع.
|
||
function syncHoldBackward() {
|
||
var notice = $("#holdBackwardNotice");
|
||
var needed = holdIsBackward();
|
||
var canForce = needed && isEditMode;
|
||
// تیک فقط وقتی معنا دارد که عقببردن مجاز باشد؛ در غیر این صورت پاک میشود.
|
||
$("#hbForceRow").toggleClass("is-hidden", !canForce);
|
||
$("#hbCreateHint").toggleClass("is-hidden", !needed || canForce);
|
||
if (!canForce) {
|
||
$("#forceHoldCheck").prop('checked', false);
|
||
$("#forceHold").val('');
|
||
}
|
||
if (!needed) {
|
||
notice.addClass("is-hidden").removeClass("is-blocking");
|
||
return;
|
||
}
|
||
$("#hbCurrent").text(jalaliDay(holdCurrentMs()));
|
||
notice.removeClass("is-hidden");
|
||
}
|
||
|
||
// تیک «عقب ببر» ⇒ فیلد مخفی force_hold برای سرور.
|
||
$("#forceHoldCheck").on('change', function() {
|
||
var checked = $(this).prop('checked');
|
||
$("#forceHold").val(checked ? '1' : '');
|
||
$("#holdBackwardNotice").toggleClass("is-blocking", !checked);
|
||
});
|
||
|
||
// هر تغییر تاریخ/نوع اقدام ⇒ وضعیت دوباره محاسبه میشود.
|
||
$("#ActionBox").on('change input', "#visitHoldUntil, #actionType",
|
||
function() { syncHoldBackward(); });
|
||
// پیکر تاریخ هم بعد از انتخاب، فیلد مخفی را پر میکند.
|
||
$(document).on('change', ".dateTimePickerHoldUntil, .dateTimePickerHoldUntil-alt",
|
||
function() { syncHoldBackward(); });
|
||
|
||
// گرفتن تأیید پیش از ثبتِ هماهنگیِ «انجامشده» (فقط در حالت ایجاد، نه ویرایش).
|
||
$("#ActionBox").on('submit', function(event) {
|
||
// (۱) در ویرایش: تاریخ عقبتر از قرار فعلی ⇒ تا تیک تأیید نزده، ارسال نمیشود.
|
||
// در «ایجاد»، وظیفه ذخیره میشود و فقط تاریخ قرار عقب نمیرود؛ سرور
|
||
// همین را با پیام روشن به کاربر میگوید، پس ارسال بلاک نمیشود.
|
||
if (isEditMode && holdIsBackward() && !$("#forceHoldCheck").prop('checked')) {
|
||
event.preventDefault();
|
||
var notice = $("#holdBackwardNotice").removeClass("is-hidden").addClass("is-blocking");
|
||
if (notice[0].scrollIntoView) {
|
||
notice[0].scrollIntoView({ block: 'center', behavior: 'smooth' });
|
||
}
|
||
notice.trigger('focus');
|
||
return;
|
||
}
|
||
// (۲) هماهنگیِ «انجامشده»: تأیید یکبارهٔ انجام کار.
|
||
if (isEditMode || holdConfirmed) {
|
||
return; // ویرایش، یا تأیید قبلی ⇒ ارسال آزاد
|
||
}
|
||
if ($("#actionType").val() !== 'hamahangi') {
|
||
return; // سایر انواع اقدام دستنخورده
|
||
}
|
||
if (!$("#checkIsDone").prop("checked")) {
|
||
return; // هماهنگیِ انجامنشده ⇒ بدون تعویق
|
||
}
|
||
event.preventDefault();
|
||
showHoldConfirm();
|
||
});
|
||
|
||
$(".actionBoxOpenB").click(function(event){
|
||
// کلیک روی کنترلهای «حذف» نباید مودال ویرایش را باز کند.
|
||
// (دکمه داخل کارت است و رویداد به والد بالا میرفت.)
|
||
if ($(event.target).closest('.ax-del-form, .ax-del').length) {
|
||
return;
|
||
}
|
||
isEditMode = true;
|
||
$("#sabtBtn05").val("ویرایش");
|
||
var actionEditUrl = "{% url 'admin_panel:customerEditAction' 1111 2222 %}";
|
||
var row = $(this).parent();
|
||
var action_id = row.attr("action_id");
|
||
var customer_id = row.attr("customer_id");
|
||
var customerHold = row.attr("customer_hold") || "";
|
||
actionEditUrl = actionEditUrl.replace('1111', customer_id);
|
||
actionEditUrl = actionEditUrl.replace('2222', action_id);
|
||
$("#ActionBox").prop("action", actionEditUrl);
|
||
$.getJSON('/panel/ActionJson/' + action_id, function(data) {
|
||
ActionParseData = JSON.parse(data);
|
||
console.log(ActionParseData);
|
||
var actionDateTime0 = new Date(ActionParseData[0]['fields']['actionDateTime']);
|
||
var finishDateTime = null;
|
||
if(ActionParseData[0]['fields']['finishDateTime'] != null){
|
||
finishDateTime = Math.floor( new Date(ActionParseData[0]['fields']['finishDateTime']).getTime() );
|
||
}
|
||
actionDateTime0 = Math.floor(actionDateTime0.getTime());
|
||
dateTimePickerAnjam.setDate(actionDateTime0);
|
||
if(finishDateTime != null){
|
||
dateTimePickerFinish.setDate(finishDateTime);
|
||
}
|
||
$("#ActionBox").addClass("is-active");
|
||
$("#actionType").val(ActionParseData[0]['fields']['actionType']);
|
||
// در ویرایش، تیکِ خودکار و تأیید نباید درگیر شوند.
|
||
holdAutoChecked = false;
|
||
holdConfirmed = false;
|
||
// فیلد «تا تاریخ پیگیری نشود» با نوع اقدام همراستا شود (در حالت ویرایش هم).
|
||
closeHoldHelp();
|
||
toggleCoordinationField(ActionParseData[0]['fields']['actionType']);
|
||
// مقدار ذخیرهشدهٔ «قرار بعدی» را در همان فیلد نشان بده (بعد از toggle،
|
||
// چون toggle برای انواع غیرهماهنگی فیلد را پاک میکند).
|
||
seedHoldPicker(customerHold);
|
||
syncHoldBackward();
|
||
$("#desc").val(ActionParseData[0]['fields']['desc']);
|
||
$("#userID").val(ActionParseData[0]['fields']['forUser']);
|
||
if(ActionParseData[0]['fields']['status'] == 'finish'){
|
||
$("#checkIsDone").prop('checked', true);
|
||
$(".showWhenDone").removeClass("is-hidden");
|
||
} else {
|
||
$("#checkIsDone").prop('checked', false);
|
||
$(".showWhenDone").addClass("is-hidden");
|
||
}
|
||
$("#actionResult").val(ActionParseData[0]['fields']['result']);
|
||
// هشدار «هماهنگی انجام شد» در ویرایش هم صرفاً نمایش داده میشود (بدون تأیید).
|
||
syncHoldWarning();
|
||
});
|
||
});
|
||
|
||
var dateTimePickerFinish = $(".dateTimePickerFinish").pDatepicker({
|
||
altField: '.dateTimePickerFinish-alt',
|
||
initialValue: true,
|
||
initialValueType: 'persian',
|
||
format: 'YYYY/MM/DD HH:mm',
|
||
calendar:{
|
||
persian: {
|
||
locale: 'fa'
|
||
}
|
||
},
|
||
timePicker: {
|
||
enabled: true,
|
||
second:{
|
||
enabled: false,
|
||
}
|
||
},
|
||
});
|
||
|
||
var dateTimePickerHoldUntil = $(".dateTimePickerHoldUntil").pDatepicker({
|
||
altField: '.dateTimePickerHoldUntil-alt',
|
||
initialValue: false,
|
||
format: 'YYYY/MM/DD',
|
||
calendar:{
|
||
persian: {
|
||
locale: 'fa'
|
||
}
|
||
},
|
||
timePicker: {
|
||
enabled: false,
|
||
second:{
|
||
enabled: false,
|
||
}
|
||
},
|
||
// بعد از انتخاب تاریخ، وضعیت «عقبتر بودن» فوراً بازمحاسبه شود
|
||
// (پیکر مقدار altField را برنامهنویسیشده مینویسد و ممکن است change رخ ندهد).
|
||
onSelect: function () {
|
||
setTimeout(function () { syncHoldBackward(); }, 0);
|
||
},
|
||
});
|
||
|
||
// اگر پیکر ساخته نشد (مثلاً نام کلاس در قالب عوض شده باشد) هشدار بده؛
|
||
// این کار جلوی خطاهای خاموش مثل «تقویم باز نمیشود» را میگیرد.
|
||
if (!dateTimePickerHoldUntil) {
|
||
console.warn('[ActionBox] pDatepicker برای «تا تاریخ پیگیری نشود» ساخته نشد؛ ' +
|
||
'کلاس .dateTimePickerHoldUntil را در قالب بررسی کنید.');
|
||
}
|
||
|
||
// فیلد «تا تاریخ پیگیری نشود» فقط برای اقدام «هماهنگی» نمایش داده میشود.
|
||
function toggleCoordinationField(actionType) {
|
||
var isCoordination = (actionType === 'hamahangi');
|
||
$(".showWhenCoordination").toggleClass("is-hidden", !isCoordination);
|
||
if (!isCoordination) {
|
||
resetHoldPicker();
|
||
closeHoldHelp(); // راهنما هم بسته شود تا در اقدام بعدی باز نماند
|
||
}
|
||
}
|
||
|
||
// ---- راهنمای بازشوندهٔ «هماهنگی» ----
|
||
function closeHoldHelp() {
|
||
$("#holdHelpPanel").addClass("is-hidden");
|
||
$("#holdHelpToggle").attr("aria-expanded", "false");
|
||
}
|
||
|
||
$("#holdHelpToggle").click(function(){
|
||
var expanded = $(this).attr("aria-expanded") === "true";
|
||
$("#holdHelpPanel").toggleClass("is-hidden", expanded);
|
||
$(this).attr("aria-expanded", expanded ? "false" : "true");
|
||
});
|
||
|
||
$("select#actionType").on('change', function(){
|
||
var type = $(this).val();
|
||
toggleCoordinationField(type);
|
||
|
||
if (type === 'hamahangi') {
|
||
// پیشفرض: «هماهنگی» یعنی همین حالا تماس گرفته شد ⇒ تیک «انجام شده».
|
||
// هشدار و تأیید، جلوی ثبتِ ناخواسته را میگیرد.
|
||
if (!$("#checkIsDone").prop("checked")) {
|
||
$("#checkIsDone").prop("checked", true);
|
||
holdAutoChecked = true;
|
||
}
|
||
} else if (holdAutoChecked) {
|
||
// تیک را خودمان زده بودیم ⇒ با تغییر نوع برمیداریم (بهویژه برای «بازدید»).
|
||
$("#checkIsDone").prop("checked", false);
|
||
holdAutoChecked = false;
|
||
}
|
||
|
||
holdConfirmed = false;
|
||
syncDoneFields();
|
||
syncHoldWarning();
|
||
});
|
||
|
||
var dateTimePickerAnjam = $(".dateTimePickerAnjam").pDatepicker({
|
||
altField: '.dateTimePickerAnjam-alt',
|
||
initialValue: true,
|
||
initialValueType: 'persian',
|
||
format: 'YYYY/MM/DD HH:mm',
|
||
calendar:{
|
||
persian: {
|
||
locale: 'fa'
|
||
}
|
||
},
|
||
timePicker: {
|
||
enabled: true,
|
||
second:{
|
||
enabled: false,
|
||
}
|
||
},
|
||
});
|
||
</script> |