improve bazdid 4
This commit is contained in:
1 parent
f86d060e4d
commit
8fd881e0ea
10 files changed
+1752
-320
No files matched your search
@@ -239,6 +239,8 @@
|
||||
|
||||
{% block bodyPage %}
|
||||
{% endblock %}
|
||||
{# بستن <div class=""> که بالاتر باز شده بود؛ پیشتر بسته نمیشد و HTML نامعتبر میشد. #}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<script>
|
||||
|
||||
@@ -164,6 +164,8 @@
|
||||
|
||||
{% block bodyPage %}
|
||||
{% endblock %}
|
||||
{# بستن <div class=""> که بالاتر باز شده بود (همان باگ base.html). #}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<script>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.ez-stats { grid-auto-flow: row; grid-template-columns: repeat(6, 1fr); overflow: visible; }
|
||||
.ez-stats { grid-auto-flow: row; grid-template-columns: repeat(4, 1fr); overflow: visible; }
|
||||
}
|
||||
.ez-stat {
|
||||
display: flex; flex-direction: column; gap: .18rem;
|
||||
@@ -41,6 +41,7 @@
|
||||
.ez-stat.warning { border-top-color: #d97706; }
|
||||
.ez-stat.link { border-top-color: #0284c7; }
|
||||
.ez-stat.violet { border-top-color: #7c3aed; }
|
||||
.ez-stat.followup { border-top-color: #0e7490; }
|
||||
|
||||
.ez-stat-top {
|
||||
display: flex; align-items: baseline; justify-content: space-between; gap: .4rem;
|
||||
@@ -69,21 +70,84 @@
|
||||
}
|
||||
.ez-legend b { font-variant-numeric: tabular-nums; color: #334155; }
|
||||
|
||||
/* ---------- ابزارکها ---------- */
|
||||
.ez-toolbar {
|
||||
display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: 0 0 .75rem;
|
||||
/* ---------- نوار تاریخ (نمای «نیازمند پیگیری») ---------- */
|
||||
.ez-datebar {
|
||||
display: flex; flex-wrap: wrap; align-items: flex-end; gap: .4rem;
|
||||
padding: .5rem .6rem; margin: .5rem 0 .4rem;
|
||||
background: #f8fbfd; border: 1px solid #d9e8f0; border-radius: .5rem;
|
||||
}
|
||||
.ez-toolbar .button { margin: 0 !important; }
|
||||
.ez-seg {
|
||||
display: inline-flex; border: 1px solid #e2e8f0; border-radius: .5rem; overflow: hidden;
|
||||
.ez-datebar .button { margin: 0 !important; }
|
||||
.ez-dateform { margin: 0; }
|
||||
.ez-datefield { display: flex; flex-direction: column; gap: .15rem; margin: 0; }
|
||||
.ez-datefield-row { display: flex; gap: .25rem; align-items: center; }
|
||||
.ez-datefield-row .input {
|
||||
height: 2.1rem; font-size: .78rem; width: 8.5rem;
|
||||
font-variant-numeric: tabular-nums; direction: ltr; text-align: center;
|
||||
}
|
||||
.ez-seg a {
|
||||
padding: .3rem .6rem; font-size: .72rem; color: #475569; text-decoration: none;
|
||||
background: #fff; border-inline-end: 1px solid #e2e8f0; white-space: nowrap;
|
||||
.ez-datenote {
|
||||
flex: 1 1 100%; font-size: .7rem; color: #64748b; line-height: 1.7;
|
||||
}
|
||||
.ez-seg a:last-child { border-inline-end: 0; }
|
||||
.ez-seg a:hover { background: #f1f5f9; }
|
||||
.ez-seg a.is-active { background: #33b5d3; color: #fff; font-weight: 700; }
|
||||
.ez-datenote b { color: #334155; }
|
||||
@media (min-width: 700px) {
|
||||
.ez-datenote { flex: 1 1 auto; }
|
||||
}
|
||||
|
||||
/* ---------- هشدار مینیمال «پیگیریهای عقبافتاده» ---------- */
|
||||
.ez-overdue-alert,
|
||||
.ez-overdue-mode {
|
||||
flex: 1 1 100%; display: inline-flex; align-items: center; gap: .35rem;
|
||||
font-size: .72rem; line-height: 1.6; text-decoration: none;
|
||||
}
|
||||
.ez-overdue-alert { color: #b91c1c; font-weight: 600; }
|
||||
.ez-overdue-alert:hover { color: #991b1b; text-decoration: underline; }
|
||||
.ez-overdue-alert b { font-variant-numeric: tabular-nums; font-size: .8rem; }
|
||||
.ez-overdue-dot {
|
||||
width: .42rem; height: .42rem; border-radius: 50%;
|
||||
background: #dc2626; flex: 0 0 auto;
|
||||
}
|
||||
.ez-overdue-mode {
|
||||
color: #7f1d1d; background: #fef2f2;
|
||||
border: 1px solid #fecaca; border-radius: .375rem; padding: .2rem .5rem;
|
||||
}
|
||||
.ez-overdue-mode b { font-variant-numeric: tabular-nums; }
|
||||
.ez-overdue-mode a {
|
||||
color: #b91c1c; font-weight: 700; text-decoration: none;
|
||||
margin-inline-start: .35rem;
|
||||
}
|
||||
.ez-overdue-mode a:hover { text-decoration: underline; }
|
||||
|
||||
/* ---------- نوار فیلتر ---------- */
|
||||
.ez-filters {
|
||||
display: flex; flex-wrap: wrap; align-items: flex-end;
|
||||
gap: .5rem; margin: .6rem 0 .4rem;
|
||||
}
|
||||
.ez-filter { display: flex; flex-direction: column; gap: .15rem; margin: 0; }
|
||||
.ez-filter-grow { flex: 1 1 18rem; min-width: 14rem; }
|
||||
.ez-filter-lbl { font-size: .68rem; color: #64748b; font-weight: 700; }
|
||||
.ez-filters .select select { font-size: .76rem; height: 2.1rem; }
|
||||
.ez-search { display: flex; gap: .25rem; align-items: center; }
|
||||
.ez-search .input { height: 2.1rem; font-size: .76rem; }
|
||||
.ez-search .button { margin: 0 !important; }
|
||||
.ez-clear { margin: 0 !important; }
|
||||
|
||||
/* ---------- سرستونهای مرتبشدنی ---------- */
|
||||
.ez-th > a {
|
||||
display: inline-flex; align-items: center; gap: .15rem;
|
||||
color: #06323d; text-decoration: none; white-space: nowrap;
|
||||
}
|
||||
.ez-th > a:hover { text-decoration: underline; }
|
||||
.ez-th.is-sorted > a { color: #0b4e60; }
|
||||
.ez-arrow { font-size: .62rem; opacity: .55; }
|
||||
.ez-th.is-sorted .ez-arrow { opacity: 1; }
|
||||
|
||||
/* ---------- تفکیک تأخیر (کلیکپذیر) ---------- */
|
||||
.ez-legend a {
|
||||
color: #64748b; text-decoration: none; padding: .05rem .35rem;
|
||||
border-radius: .25rem; white-space: nowrap;
|
||||
}
|
||||
.ez-legend a:hover { background: #f1f5f9; }
|
||||
.ez-legend a.is-active { background: #33b5d3; color: #fff; }
|
||||
.ez-legend a.is-active b { color: #fff; }
|
||||
|
||||
/* ---------- جدول ---------- */
|
||||
.ez-table { width: 100%; margin: 0; font-size: .82rem; border-collapse: collapse; }
|
||||
@@ -196,134 +260,231 @@
|
||||
<div class="ez-wrap">
|
||||
<div class="columns m-0">
|
||||
<div class="column is-12 p-0">
|
||||
{# ===== نوار آمار: هر عدد لینک فیلتر ===== #}
|
||||
{# ===== نوار آمار: چهار کارت، هر عدد لینک فیلتر ===== #}
|
||||
<div class="ez-stats-head">
|
||||
<p class="ez-stats-title">وضعیت مشتریانِ عقبافتاده</p>
|
||||
<p class="ez-stats-title">وضعیت پیگیری مشتریان</p>
|
||||
<p class="ez-stats-hint">
|
||||
«عقبافتاده» یعنی از آخرین بازدید
|
||||
<b>بیش از {{ counts.period_months }} ماه</b> گذشته باشد.
|
||||
روی هر کارت بزنید تا فقط همان گروه نمایش داده شود؛
|
||||
<b>کل = بدون قرار + با قرار</b>.
|
||||
سه کارتِ آخر سه نوع قرارِ جدا هستند؛ یک مشتری میتواند بیش از
|
||||
یکی داشته باشد، پس جمع آنها ممکن است از «با قرار» بیشتر شود.
|
||||
<b>کل = تعیینتکلیفنشده + تعیینتکلیفشده</b>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="ez-stats">
|
||||
<a href="?view=all&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat total {% if view == 'all' %}is-active{% endif %}"
|
||||
title="همهٔ مشتریان عقبافتاده، با هر وضعیت قرار">
|
||||
{# کارت «نیازمند پیگیری امروز» — مستقل از «عقبافتاده»؛ بازدیدها حذف میشوند. #}
|
||||
<a href="{{ view_links.today }}"
|
||||
class="ez-stat followup {% if view == followup_view %}is-active{% endif %}"
|
||||
title="مشتریانی که موعد پیگیری/تماسشان امروز است و برایشان بازدید برنامهریزی نشده">
|
||||
<span class="ez-stat-top">
|
||||
<span class="ez-lbl">کل عقبافتادهها</span>
|
||||
<span class="ez-num">{{ counts.total }}</span>
|
||||
<span class="ez-lbl">نیازمند پیگیری امروز</span>
|
||||
<span class="ez-num has-text-info">{{ counts.followup_today }}</span>
|
||||
</span>
|
||||
<span class="ez-desc">همه، فارغ از داشتن یا نداشتن قرار</span>
|
||||
<span class="ez-desc">موعد تماسشان امروز است — بازدید ندارند</span>
|
||||
</a>
|
||||
|
||||
<a href="?view=uncoordinated&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat danger {% if view == 'uncoordinated' %}is-active{% endif %}"
|
||||
title="مشتریانی که هنوز هیچ قرار بعدی برایشان ثبت نشده است">
|
||||
<a href="{{ view_links.all }}"
|
||||
class="ez-stat total {% if view == 'all' %}is-active{% endif %}"
|
||||
title="همهٔ مشتریانی که بازدیدشان عقب افتاده، با هر وضعیت پیگیری">
|
||||
<span class="ez-stat-top">
|
||||
<span class="ez-lbl">بدون قرار</span>
|
||||
<span class="ez-lbl">همهٔ مشتریان عقبافتاده</span>
|
||||
<span class="ez-num">{{ counts.total }}</span>
|
||||
</span>
|
||||
<span class="ez-desc">با هر وضعیت پیگیری</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ view_links.uncoordinated }}"
|
||||
class="ez-stat danger {% if view == 'uncoordinated' %}is-active{% endif %}"
|
||||
title="مشتریانی که هنوز هیچ وقت بازدید/پیگیری برایشان تعیین نشده است">
|
||||
<span class="ez-stat-top">
|
||||
<span class="ez-lbl">تعیین تکلیف نشده</span>
|
||||
<span class="ez-num has-text-danger">{{ counts.uncoordinated }}</span>
|
||||
</span>
|
||||
<span class="ez-desc">هنوز وقت بازدید تعیین نشده — نیاز به تماس</span>
|
||||
</a>
|
||||
|
||||
<a href="?view=coordinated&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
<a href="{{ view_links.coordinated }}"
|
||||
class="ez-stat success {% if view == 'coordinated' %}is-active{% endif %}"
|
||||
title="مشتریانی که وقت بازدید بعدی برایشان مشخص شده است">
|
||||
title="مشتریانی که وقت بازدید یا پیگیریِ بعدی برایشان تعیین شده است">
|
||||
<span class="ez-stat-top">
|
||||
<span class="ez-lbl">با قرار</span>
|
||||
<span class="ez-lbl">تعیین تکلیف شده</span>
|
||||
<span class="ez-num has-text-success">{{ counts.coordinated }}</span>
|
||||
</span>
|
||||
<span class="ez-desc">وقت بازدیدشان مشخص است (هر دو نوع قرار)</span>
|
||||
</a>
|
||||
|
||||
<a href="?view=manual&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat warning {% if view == 'manual' %}is-active{% endif %}"
|
||||
title="قرار تعویق که از فرم «هماهنگی» ثبت شده است">
|
||||
<span class="ez-stat-top">
|
||||
<span class="ez-lbl">قرار هماهنگی</span>
|
||||
<span class="ez-num has-text-warning-dark">{{ counts.manual }}</span>
|
||||
</span>
|
||||
<span class="ez-desc">تعویق دستی از فرم هماهنگی (مثلاً «ماه بعد زنگ بزنید»)</span>
|
||||
</a>
|
||||
|
||||
<a href="?view=scheduled&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat link {% if view == 'scheduled' %}is-active{% endif %}"
|
||||
title="اقدام «بازدید» با تاریخ آینده">
|
||||
<span class="ez-stat-top">
|
||||
<span class="ez-lbl">بازدید برنامهریزیشده</span>
|
||||
<span class="ez-num has-text-link">{{ counts.scheduled }}</span>
|
||||
</span>
|
||||
<span class="ez-desc">اقدام «بازدید» با تاریخ آینده ثبت شده است</span>
|
||||
</a>
|
||||
|
||||
<a href="?view=coordination&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat violet {% if view == 'coordination' %}is-active{% endif %}"
|
||||
title="اقدام «هماهنگی» با تاریخ پیگیری در آینده">
|
||||
<span class="ez-stat-top">
|
||||
<span class="ez-lbl">هماهنگی</span>
|
||||
<span class="ez-num" style="color:#7c3aed">{{ counts.coordination }}</span>
|
||||
</span>
|
||||
<span class="ez-desc">تماس گرفته شده و پیگیری به آینده موکول شده است</span>
|
||||
<span class="ez-desc">وقت بعدیشان مشخص است</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{# تفکیک مدت تأخیر در نمای جاری #}
|
||||
<div class="ez-legend">
|
||||
<span>میزان تأخیر در همین نما:</span>
|
||||
<span><b>{{ counts.buckets.lt30 }}</b> تا ۳۰ روز</span>
|
||||
<span><b>{{ counts.buckets.30to90 }}</b> ۳۰ تا ۹۰ روز</span>
|
||||
<span><b>{{ counts.buckets.90to180 }}</b> ۹۰ تا ۱۸۰ روز</span>
|
||||
<span><b>{{ counts.buckets.gt180 }}</b> بیش از ۶ ماه</span>
|
||||
</div>
|
||||
{# ===== نوار تاریخ در نمای «نیازمند پیگیری» ===== #}
|
||||
{% if is_followup_view %}
|
||||
<div class="ez-datebar">
|
||||
<a href="{{ followup_nav.prev }}" class="button is-small is-light"
|
||||
title="روز قبل">‹ روز قبل</a>
|
||||
|
||||
{# ===== ابزارکها: جستجو و مرتبسازی ===== #}
|
||||
<div class="ez-toolbar">
|
||||
<a href="#" id="openSearchBox" class="button is-info is-outlined is-rounded is-small">
|
||||
جستجو{% if searchVal %}: «{{ searchVal }}»{% endif %}
|
||||
</a>
|
||||
<form method="get" class="ez-dateform">
|
||||
<input type="hidden" name="view" value="{{ followup_view }}">
|
||||
{% if searchVal %}<input type="hidden" name="searchVal" value="{{ searchVal }}">{% endif %}
|
||||
{% if searchVal %}<input type="hidden" name="searchOn" value="{{ searchOn }}">{% endif %}
|
||||
<label class="ez-datefield">
|
||||
<span class="ez-filter-lbl">تاریخ پیگیری (شمسی)</span>
|
||||
<span class="ez-datefield-row">
|
||||
<input type="text" name="fdate" id="followupDatePicker"
|
||||
value="{{ followup_date_jalali }}" class="input is-small ss02"
|
||||
placeholder="۱۴۰۵/۰۸/۲۹" autocomplete="off" inputmode="numeric">
|
||||
<button type="submit" class="button is-info is-small">نمایش</button>
|
||||
</span>
|
||||
</label>
|
||||
</form>
|
||||
|
||||
<span class="is-size-7 has-text-grey">مرتبسازی</span>
|
||||
<span class="ez-seg">
|
||||
<a href="?view={{ view }}&sort=oldest{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="{% if sort == 'oldest' %}is-active{% endif %}">قدیمیترین</a>
|
||||
<a href="?view={{ view }}&sort=overdue{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="{% if sort == 'overdue' %}is-active{% endif %}">بیشترین تأخیر</a>
|
||||
<a href="?view={{ view }}&sort=newest{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="{% if sort == 'newest' %}is-active{% endif %}">جدیدترین</a>
|
||||
<a href="{{ followup_nav.next }}" class="button is-small is-light"
|
||||
title="روز بعد">روز بعد ›</a>
|
||||
|
||||
{% if not followup_nav.is_today %}
|
||||
<a href="{{ followup_nav.today }}" class="button is-success is-light is-small">
|
||||
بازگشت به امروز
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<span class="ez-datenote">
|
||||
{% if followup_nav.is_today %}
|
||||
فقط موعدهای <b>امروز</b> نمایش داده میشوند.
|
||||
{% else %}
|
||||
نمایش موعدهای <b>{{ followup_date_jalali }}</b> (نه امروز).
|
||||
{% endif %}
|
||||
مشتریانی که برایشان <b>بازدید</b> گذاشته شده در این فهرست نمیآیند.
|
||||
</span>
|
||||
|
||||
{% if searchVal %}
|
||||
<a href="?view={{ view }}&sort={{ sort }}" class="button is-small is-light">حذف جستجو</a>
|
||||
{# هشدار مینیمال: موعدهایی که گذشتهاند و هنوز تعیین تکلیف نشدهاند. #}
|
||||
{% if counts.followup_overdue and not show_missed %}
|
||||
<a class="ez-overdue-alert"
|
||||
href="{{ followup_overdue_link }}"
|
||||
title="موعد پیگیریشان گذشته و هنوز تعیین تکلیف نشدهاند — برای دیدن فهرستشان کلیک کنید">
|
||||
<span class="ez-overdue-dot" aria-hidden="true"></span>
|
||||
<b>{{ counts.followup_overdue }}</b> مورد نیازمند پیگیری از روزهای قبل باقی مانده
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if show_missed %}
|
||||
<span class="ez-overdue-mode">
|
||||
نمایش <b>{{ counts.followup_overdue }}</b> پیگیریِ عقبافتاده
|
||||
<a href="{{ followup_ontime_link }}" title="بازگشت به فهرست امروز">✕ بازگشت به امروز</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# ===== نوار فیلتر و جستوجو: یک ردیف، همهٔ کنترلها ===== #}
|
||||
<form class="ez-filters" method="get" action="">
|
||||
{% if is_followup_view %}
|
||||
<input type="hidden" name="fdate" value="{{ followup_date_jalali }}">
|
||||
{% endif %}
|
||||
{# حالت «فقط عقبافتادهها» هنگام جستوجو/فیلتر حفظ شود. #}
|
||||
{% if show_missed %}
|
||||
<input type="hidden" name="missed" value="1">
|
||||
{% endif %}
|
||||
<label class="ez-filter">
|
||||
<span class="ez-filter-lbl">نوع قرار</span>
|
||||
<span class="select is-small">
|
||||
<select name="view" class="ez-auto-submit">
|
||||
<option value="today" {% if is_followup_view %}selected{% endif %}>نیازمند پیگیری (تاریخ انتخابی)</option>
|
||||
<option value="all" {% if view == 'all' %}selected{% endif %}>همه (با و بدون قرار)</option>
|
||||
<option value="uncoordinated" {% if view == 'uncoordinated' %}selected{% endif %}>تعیین تکلیف نشده</option>
|
||||
<option value="coordinated" {% if view == 'coordinated' %}selected{% endif %}>تعیین تکلیف شده (همه)</option>
|
||||
<option value="manual" {% if view == 'manual' %}selected{% endif %}>تعویق دستی</option>
|
||||
<option value="scheduled" {% if view == 'scheduled' %}selected{% endif %}>بازدید برنامهریزیشده</option>
|
||||
<option value="coordination" {% if view == 'coordination' %}selected{% endif %}>پیگیری تلفنی</option>
|
||||
</select>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
{% if not is_followup_view %}
|
||||
<label class="ez-filter">
|
||||
<span class="ez-filter-lbl">میزان تأخیر</span>
|
||||
<span class="select is-small">
|
||||
<select name="delay" class="ez-auto-submit">
|
||||
<option value="" {% if not delay %}selected{% endif %}>همه</option>
|
||||
<option value="lt30" {% if delay == 'lt30' %}selected{% endif %}>تا ۳۰ روز ({{ counts.buckets.lt30 }})</option>
|
||||
<option value="30to90" {% if delay == '30to90' %}selected{% endif %}>۳۰ تا ۹۰ روز ({{ counts.buckets.30to90 }})</option>
|
||||
<option value="90to180" {% if delay == '90to180' %}selected{% endif %}>۹۰ تا ۱۸۰ روز ({{ counts.buckets.90to180 }})</option>
|
||||
<option value="gt180" {% if delay == 'gt180' %}selected{% endif %}>بیش از ۶ ماه ({{ counts.buckets.gt180 }})</option>
|
||||
</select>
|
||||
</span>
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<label class="ez-filter">
|
||||
<span class="ez-filter-lbl">مرتبسازی</span>
|
||||
<span class="select is-small">
|
||||
<select name="sort" class="ez-auto-submit">
|
||||
<option value="last_visit" {% if sort == 'last_visit' and sort_dir == 'asc' %}selected{% endif %}>قدیمیترین بازدید</option>
|
||||
<option value="last_visit-desc" {% if sort == 'last_visit' and sort_dir == 'desc' %}selected{% endif %}>جدیدترین بازدید</option>
|
||||
<option value="overdue" {% if sort == 'overdue' %}selected{% endif %}>بیشترین تأخیر</option>
|
||||
<option value="name" {% if sort == 'name' %}selected{% endif %}>نام (الفبا)</option>
|
||||
<option value="status" {% if sort == 'status' %}selected{% endif %}>وضعیت قرار</option>
|
||||
<option value="coordination" {% if sort == 'coordination' %}selected{% endif %}>تاریخ پیگیری</option>
|
||||
</select>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label class="ez-filter ez-filter-grow">
|
||||
<span class="ez-filter-lbl">جستوجو</span>
|
||||
<span class="ez-search">
|
||||
<input type="text" name="searchVal" value="{{ searchVal }}"
|
||||
class="input is-small" placeholder="نام، تلفن، کد یا آدرس">
|
||||
<span class="select is-small">
|
||||
<select name="searchOn">
|
||||
<option value="name" {% if searchOn == 'name' %}selected{% endif %}>نام</option>
|
||||
<option value="phone" {% if searchOn == 'phone' %}selected{% endif %}>تلفن</option>
|
||||
<option value="code" {% if searchOn == 'code' %}selected{% endif %}>کد</option>
|
||||
<option value="address" {% if searchOn == 'address' %}selected{% endif %}>آدرس</option>
|
||||
</select>
|
||||
</span>
|
||||
<button type="submit" class="button is-info is-small">جستوجو</button>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
{% if has_filters %}
|
||||
<a href="{{ clear_link }}" class="button is-light is-small ez-clear">✕ حذف فیلترها</a>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{# تفکیک مدت تأخیر در نمای جاری (کلیکپذیر) #}
|
||||
{% if not is_followup_view %}
|
||||
<div class="ez-legend">
|
||||
<span>میزان تأخیر در همین نما:</span>
|
||||
<a href="{{ delay_links.ez_all }}" class="{% if not delay %}is-active{% endif %}">
|
||||
<b>{{ counts.view_total }}</b> همه
|
||||
</a>
|
||||
<a href="{{ delay_links.lt30 }}" class="{% if delay == 'lt30' %}is-active{% endif %}">
|
||||
<b>{{ counts.buckets.lt30 }}</b> تا ۳۰ روز
|
||||
</a>
|
||||
<a href="{{ delay_links.30to90 }}" class="{% if delay == '30to90' %}is-active{% endif %}">
|
||||
<b>{{ counts.buckets.30to90 }}</b> ۳۰ تا ۹۰ روز
|
||||
</a>
|
||||
<a href="{{ delay_links.90to180 }}" class="{% if delay == '90to180' %}is-active{% endif %}">
|
||||
<b>{{ counts.buckets.90to180 }}</b> ۹۰ تا ۱۸۰ روز
|
||||
</a>
|
||||
<a href="{{ delay_links.gt180 }}" class="{% if delay == 'gt180' %}is-active{% endif %}">
|
||||
<b>{{ counts.buckets.gt180 }}</b> بیش از ۶ ماه
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="table-container">
|
||||
<table class="table ez-table">
|
||||
<colgroup>
|
||||
<col style="width: 21%">
|
||||
<col style="width: 12%">
|
||||
<col style="width: 10%">
|
||||
<col style="width: 10%">
|
||||
<col style="width: 10%">
|
||||
<col style="width: 9%">
|
||||
<col style="width: 8%">
|
||||
<col style="width: 9%">
|
||||
<col style="width: 11%">
|
||||
{% for col in table_columns %}
|
||||
<col style="width: {{ col.width }}%">
|
||||
{% endfor %}
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>نام و نام خانوادگی</th>
|
||||
<th>وضعیت قرار</th>
|
||||
<th>قرار دستی</th>
|
||||
<th>بازدید برنامهریزیشده</th>
|
||||
<th>هماهنگی</th>
|
||||
<th>آخرین بازدید</th>
|
||||
<th>تأخیر</th>
|
||||
<th>تلفن</th>
|
||||
<th>آدرس</th>
|
||||
{% for col in sort_header %}
|
||||
<th class="ez-th {% if col.active %}is-sorted{% endif %}">
|
||||
<a href="{{ col.link }}" title="مرتبسازی بر اساس {{ col.label }}">
|
||||
{{ col.label }}<span class="ez-arrow">{% if col.active %}{% if col.dir == 'asc' %}▲{% else %}▼{% endif %}{% else %}⇅{% endif %}</span>
|
||||
</a>
|
||||
</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -364,6 +525,7 @@
|
||||
<td data-label="آخرین بازدید" class="ez-num ez-nowrap lastView">
|
||||
{% if appt.last_visit %}{{ appt.last_visit|toJalali }}{% else %}<span class="ez-muted">بدون بازدید</span>{% endif %}
|
||||
</td>
|
||||
{% if 'overdue' not in hidden_columns %}
|
||||
<td data-label="تأخیر" class="ez-nowrap">
|
||||
{% if appt.overdue_days >= 180 %}
|
||||
<span class="ez-late lv3">{{ appt.overdue_days }} روز</span>
|
||||
@@ -375,6 +537,7 @@
|
||||
<span class="ez-late lv0">{{ appt.overdue_days }} روز</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<td data-label="تلفن" class="ez-nowrap">
|
||||
@@ -397,8 +560,14 @@
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="9" class="has-text-centered py-5">
|
||||
<span class="has-text-grey">موردی در این نما پیدا نشد.</span>
|
||||
<td colspan="{{ column_count }}" class="has-text-centered py-5">
|
||||
<span class="has-text-grey">
|
||||
{% if is_followup_view %}
|
||||
برای تاریخ {{ followup_date_jalali }} موردی برای پیگیری نیست.
|
||||
{% else %}
|
||||
موردی در این نما پیدا نشد.
|
||||
{% endif %}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -409,7 +578,7 @@
|
||||
{# ===== صفحهبندی ===== #}
|
||||
<div class="is-flex is-align-items-center is-justify-content-space-between mt-3 mb-5">
|
||||
{% if customers.has_previous %}
|
||||
<a class="button is-danger is-small" href="?view={{ view }}&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}&page={{ customers.previous_page_number }}">صفحه قبل</a>
|
||||
<a class="button is-danger is-small" href="{{ page_prev }}">صفحه قبل</a>
|
||||
{% else %}<span></span>{% endif %}
|
||||
|
||||
<span class="is-size-7 has-text-grey">
|
||||
@@ -418,60 +587,57 @@
|
||||
</span>
|
||||
|
||||
{% if customers.has_next %}
|
||||
<a class="button is-danger is-small" href="?view={{ view }}&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}&page={{ customers.next_page_number }}">صفحه بعد</a>
|
||||
<a class="button is-danger is-small" href="{{ page_next }}">صفحه بعد</a>
|
||||
{% else %}<span></span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal SearchBox">
|
||||
<div class="modal-background closeSearch"></div>
|
||||
<div class="modal-content">
|
||||
<form method="get" class="columns is-mobile is-multiline">
|
||||
{# حفظ نما و ترتیب هنگام جستوجو #}
|
||||
<input type="hidden" name="view" value="{{ view }}">
|
||||
<input type="hidden" name="sort" value="{{ sort }}">
|
||||
<div class="field column is-7-desktop is-12-mobile m-0">
|
||||
<label class="label">جستجو کنید</label>
|
||||
<div class="control">
|
||||
<input name="searchVal" class="input search" type="text" value="{{ searchVal }}" placeholder="نام، تلفن، کد یا آدرس">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-5-desktop is-12-mobile m-0">
|
||||
<label class="label">فیلد</label>
|
||||
<div class="select is-fullwidth">
|
||||
<select name="searchOn">
|
||||
<option value="name" {% if searchOn == 'name' %}selected{% endif %}>نام و نام خانوادگی</option>
|
||||
<option value="phone" {% if searchOn == 'phone' %}selected{% endif %}>تلفن</option>
|
||||
<option value="address" {% if searchOn == 'address' %}selected{% endif %}>آدرس</option>
|
||||
<option value="code" {% if searchOn == 'code' %}selected{% endif %}>کد مشتری</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-12-desktop is-12-mobile m-0">
|
||||
<input class="button is-success is-fullwidth" id="searchbtn" value="جستجو مشتری" type="submit">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
<button class="modal-close is-large closeSearch" aria-label="close"></button>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block jsEnd %}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#openSearchBox").click(function(e) {
|
||||
e.preventDefault();
|
||||
$(".SearchBox").addClass("is-active");
|
||||
});
|
||||
$(".closeSearch").click(function() {
|
||||
$(".SearchBox").removeClass("is-active");
|
||||
// تغییر هر دراپداون ⇒ ارسال خودکار فرم فیلترها.
|
||||
$(".ez-auto-submit").on('change', function () {
|
||||
$(this).closest('form').trigger('submit');
|
||||
});
|
||||
|
||||
// مقدار «مرتبسازی» با علامتِ جهت ترکیب میشود (مثلاً last_visit-desc)
|
||||
// تا یک دراپداون بتواند هر دو جهت را پوشش دهد.
|
||||
$(".ez-filters select[name=sort]").on('change', function () {
|
||||
var value = $(this).val() || '';
|
||||
var form = $(this).closest('form');
|
||||
var dash = value.lastIndexOf('-');
|
||||
if (dash > -1) {
|
||||
form.find("input[name=sort]").val(value.slice(0, dash));
|
||||
form.find("input[name=dir]").val(value.slice(dash + 1));
|
||||
} else {
|
||||
form.find("input[name=sort]").val(value);
|
||||
form.find("input[name=dir]").val('');
|
||||
}
|
||||
});
|
||||
|
||||
// تقویم شمسی برای ناوبری روزهای نمای «نیازمند پیگیری».
|
||||
// همان کامپوننت pDatepicker که در بقیهٔ صفحهها استفاده شده است.
|
||||
{% if is_followup_view %}
|
||||
var $followupDate = $("#followupDatePicker");
|
||||
if ($followupDate.length && typeof $followupDate.pDatepicker === 'function') {
|
||||
$followupDate.pDatepicker({
|
||||
initialValue: false,
|
||||
initialValueType: 'persian',
|
||||
format: 'YYYY/MM/DD',
|
||||
autoClose: true,
|
||||
calendar: {
|
||||
persian: { locale: 'fa', leapYearMode: 'astronomical' }
|
||||
},
|
||||
onSelect: function () {
|
||||
// انتخاب تاریخ ⇒ فوراً همان روز نمایش داده شود.
|
||||
$followupDate.closest('form').trigger('submit');
|
||||
}
|
||||
});
|
||||
}
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in new issue
Block a user