improve bazdid
This commit is contained in:
1 parent
2aee85593f
commit
534a84f977
12 files changed
+2305
-339
No files matched your search
@@ -161,27 +161,160 @@
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* ===== مودال «ایجاد/ویرایش وظیفه» — 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; }
|
||||
|
||||
#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 %}">
|
||||
{% else %}
|
||||
<form id="ActionBox" class="modal" method="post" action="">
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% csrf_token %}
|
||||
<div class="modal-background closeActionBox"></div>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title is-hidden">ایجاد وظیفه</p>
|
||||
<button type="button" class="delete closeActionBox" aria-label="close"></button>
|
||||
<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">
|
||||
|
||||
<div class="columns is-mobile is-multiline">
|
||||
<div class="field column is-6-desktop is-12-mobile m-0">
|
||||
<label class="label">نوع اقدام</label>
|
||||
<div class="control">
|
||||
<div class="select" style="width: 100%;">
|
||||
<select id="actionType" required name="actionType" style="width: 100%;">
|
||||
<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>
|
||||
@@ -192,29 +325,11 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-6-desktop is-12-mobile m-0">
|
||||
<label class="label">تاریخ و ساعتی که کار باید انجام شود</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input dateTimePickerAnjam">
|
||||
<input id="dateTimeAnjam" name="dateTimeAnjam" required type="text" class="input is-hidden dateTimePickerAnjam-alt">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-12-desktop is-12-mobile m-0">
|
||||
<div class="control">
|
||||
<label class="label mb-0">توضیحات برای یادآوری حین انجام کار:</label>
|
||||
<p class="is-size-7">راجب کاری که در آینده میخواهید انجام دهید توضیحاتی را بنویسید</p>
|
||||
<textarea id="desc" required name="desc" class="textarea" placeholder="مثلا: بامشتری تماس بگیرم برای هماهنگی تعویض فیلتر دستگاه"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-6-desktop is-12-mobile m-0">
|
||||
<label class="label">توسط</label>
|
||||
<div class="control">
|
||||
<div class="select" style="width: 100%;">
|
||||
<select id="userID" required name="userID" style="width: 100%;">
|
||||
|
||||
<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 %}
|
||||
@@ -228,47 +343,153 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-12-desktop is-12-mobile m-0">
|
||||
<div class="control">
|
||||
<label class="checkbox">
|
||||
<input name="is_done" id="checkIsDone" type="checkbox">
|
||||
این کار انجام شده
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-12-desktop is-12-mobile m-0 showWhenDone is-hidden">
|
||||
<label class="label">تاریخ و ساعت اتمام کار</label>
|
||||
<div class="control">
|
||||
<input id="FinishDateTime" type="text" class="input dateTimePickerFinish">
|
||||
<input name="FinishDateTime" type="text" class="input dateTimePickerFinish-alt is-hidden">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-12-desktop is-12-mobile m-0 showWhenDone is-hidden">
|
||||
<div class="control">
|
||||
<label class="label mb-0">نتیجه</label>
|
||||
<p class="is-size-7">نتیجه کار یا پیگیری که انجام داده اید را بنویسید</p>
|
||||
<textarea name="result" id="actionResult" class="textarea" placeholder="نتیجه فعالیت انجام شده را بنویسید"></textarea>
|
||||
</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-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> اگر قرار ۲۲ آذر باشد و همکار دیگری ۳۰ آذر بگذارد،
|
||||
قرار به ۳۰ آذر میرود؛ اما ۱۵ آذر نادیده گرفته میشود. برای کوتاهکردن،
|
||||
هماهنگی را حذف و دوباره ثبت کنید.</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">
|
||||
<button type="button" class="button closeActionBox">لغو</button>
|
||||
<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;
|
||||
|
||||
// پیکر «تا تاریخ پیگیری نشود» را ریست میکند.
|
||||
// نکته: pDatepicker یک Model برمیگرداند؛ اگر سلکتور هیچ المانی پیدا نکند
|
||||
// مقدار undefined میشود. بدون این محافظ، یک ناهمخوانی نام کلاس باعث
|
||||
// TypeError میشد و بقیهٔ منطقِ هندلر (پنهانکردن فیلدها، برداشتن تیک خودکار)
|
||||
// اجرا نمیشد.
|
||||
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 %}";
|
||||
@@ -282,18 +503,77 @@
|
||||
$("#actionResult").val('');
|
||||
dateTimePickerAnjam.setDate();
|
||||
dateTimePickerFinish.setDate();
|
||||
resetHoldPicker();
|
||||
$(".showWhenCoordination").addClass("is-hidden");
|
||||
closeHoldHelp();
|
||||
$("#sabtBtn05").val("ثبت");
|
||||
});
|
||||
|
||||
$("#checkIsDone").change(function() {
|
||||
if(this.checked) {
|
||||
$(".showWhenDone").removeClass("is-hidden");
|
||||
} else {
|
||||
$(".showWhenDone").addClass("is-hidden");
|
||||
// نمایش/پنهانکردن فیلدهای «انجام شده».
|
||||
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');
|
||||
});
|
||||
|
||||
// گرفتن تأیید پیش از ثبتِ هماهنگیِ «انجامشده» (فقط در حالت ایجاد، نه ویرایش).
|
||||
$("#ActionBox").on('submit', function(event) {
|
||||
if (isEditMode || holdConfirmed) {
|
||||
return; // ویرایش، یا تأیید قبلی ⇒ ارسال آزاد
|
||||
}
|
||||
if ($("#actionType").val() !== 'hamahangi') {
|
||||
return; // سایر انواع اقدام دستنخورده
|
||||
}
|
||||
if (!$("#checkIsDone").prop("checked")) {
|
||||
return; // هماهنگیِ انجامنشده ⇒ بدون تعویق
|
||||
}
|
||||
event.preventDefault();
|
||||
showHoldConfirm();
|
||||
});
|
||||
|
||||
$(".actionBoxOpenB").click(function(){
|
||||
isEditMode = true;
|
||||
$("#sabtBtn05").val("ویرایش");
|
||||
var actionEditUrl = "{% url 'admin_panel:customerEditAction' 1111 2222 %}";
|
||||
var action_id = $(this).parent().attr("action_id");
|
||||
@@ -316,6 +596,12 @@
|
||||
}
|
||||
$("#ActionBox").addClass("is-active");
|
||||
$("#actionType").val(ActionParseData[0]['fields']['actionType']);
|
||||
// در ویرایش، تیکِ خودکار و تأیید نباید درگیر شوند.
|
||||
holdAutoChecked = false;
|
||||
holdConfirmed = false;
|
||||
// فیلد «تا تاریخ پیگیری نشود» با نوع اقدام همراستا شود (در حالت ویرایش هم).
|
||||
closeHoldHelp();
|
||||
toggleCoordinationField(ActionParseData[0]['fields']['actionType']);
|
||||
$("#desc").val(ActionParseData[0]['fields']['desc']);
|
||||
$("#userID").val(ActionParseData[0]['fields']['forUser']);
|
||||
if(ActionParseData[0]['fields']['status'] == 'finish'){
|
||||
@@ -326,6 +612,8 @@
|
||||
$(".showWhenDone").addClass("is-hidden");
|
||||
}
|
||||
$("#actionResult").val(ActionParseData[0]['fields']['result']);
|
||||
// هشدار «هماهنگی انجام شد» در ویرایش هم صرفاً نمایش داده میشود (بدون تأیید).
|
||||
syncHoldWarning();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -347,6 +635,74 @@
|
||||
},
|
||||
});
|
||||
|
||||
var dateTimePickerHoldUntil = $(".dateTimePickerHoldUntil").pDatepicker({
|
||||
altField: '.dateTimePickerHoldUntil-alt',
|
||||
initialValue: false,
|
||||
format: 'YYYY/MM/DD',
|
||||
calendar:{
|
||||
persian: {
|
||||
locale: 'fa'
|
||||
}
|
||||
},
|
||||
timePicker: {
|
||||
enabled: false,
|
||||
second:{
|
||||
enabled: false,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// اگر پیکر ساخته نشد (مثلاً نام کلاس در قالب عوض شده باشد) هشدار بده؛
|
||||
// این کار جلوی خطاهای خاموش مثل «تقویم باز نمیشود» را میگیرد.
|
||||
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,
|
||||
|
||||
@@ -2,109 +2,379 @@
|
||||
{% load custom_tags %}
|
||||
{% block bodyPage %}
|
||||
|
||||
<div class="">
|
||||
<div class="columns m-0">
|
||||
<style>
|
||||
/* ===================================================================
|
||||
صفحهٔ انتظار بازدید — mobile first
|
||||
مقیاس فاصله: ۰٫۲۵rem (۴px) — همهٔ فاصلهها مضرب همین واحد است.
|
||||
=================================================================== */
|
||||
.ez-wrap { padding: .5rem; }
|
||||
@media (min-width: 769px) { .ez-wrap { padding: 1rem 1.25rem; } }
|
||||
|
||||
<div class="column is-12">
|
||||
<div class="buttons">
|
||||
<a href="#" id="openSearchBox" class="button is-info is-outlined is-rounded mr-0">جستجو</a>
|
||||
/* ---------- نوار آمار ---------- */
|
||||
.ez-stats {
|
||||
display: grid; grid-auto-flow: column; grid-auto-columns: minmax(8.5rem, 1fr);
|
||||
gap: .5rem; overflow-x: auto; padding-bottom: .25rem;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.ez-stats { grid-auto-flow: row; grid-template-columns: repeat(5, 1fr); overflow: visible; }
|
||||
}
|
||||
.ez-stat {
|
||||
display: block; border: 1px solid #e2e8f0; border-radius: .625rem;
|
||||
background: #fff; padding: .55rem .7rem; text-decoration: none; color: #334155;
|
||||
transition: border-color .15s ease, background-color .15s ease;
|
||||
}
|
||||
.ez-stat:hover { border-color: #94a3b8; }
|
||||
.ez-stat .ez-num {
|
||||
display: block; font-size: 1.2rem; font-weight: 800; line-height: 1.1;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.ez-stat .ez-lbl { display: block; margin-top: .15rem; font-size: .7rem; color: #64748b; }
|
||||
.ez-stat.is-active {
|
||||
border-color: #33b5d3; background: #f1fbff; box-shadow: inset 0 -3px 0 #33b5d3;
|
||||
}
|
||||
.ez-stat.is-active .ez-lbl { color: #0e7490; font-weight: 700; }
|
||||
|
||||
/* ---------- تفکیک تأخیر ---------- */
|
||||
.ez-legend {
|
||||
display: flex; flex-wrap: wrap; gap: .25rem .9rem;
|
||||
margin: .6rem 0 .5rem; font-size: .72rem; color: #64748b;
|
||||
}
|
||||
.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-toolbar .button { margin: 0 !important; }
|
||||
.ez-seg {
|
||||
display: inline-flex; border: 1px solid #e2e8f0; border-radius: .5rem; overflow: hidden;
|
||||
}
|
||||
.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-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-table { width: 100%; margin: 0; font-size: .82rem; border-collapse: collapse; }
|
||||
@media (min-width: 900px) { .ez-table { table-layout: fixed; } }
|
||||
.ez-table thead th {
|
||||
position: sticky; top: 0; z-index: 2; background: #33b5d3; color: #06323d;
|
||||
font-size: .72rem; font-weight: 700; padding: .5rem .35rem; white-space: nowrap;
|
||||
border: 0; border-bottom: 1px solid #22a5c1;
|
||||
}
|
||||
.ez-table tbody td {
|
||||
padding: .45rem .3rem; vertical-align: middle; text-align: center;
|
||||
line-height: 1.4; border: 0; border-bottom: 1px solid #eef2f6;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
/* تاریخها و شمارهها هرگز به دو خط نشکنند */
|
||||
.ez-table tbody td.ez-nowrap { white-space: nowrap; }
|
||||
.ez-table tbody tr:hover td { background: #f8fbfd; }
|
||||
|
||||
/* شمارندهٔ ردیف: بهجای یک ستون کامل، چیپ کنار نام */
|
||||
.ez-idx {
|
||||
display: inline-block; min-width: 1.55rem; margin-inline-end: .3rem;
|
||||
padding: .05rem .25rem; border-radius: .3rem; background: #f1f5f9;
|
||||
color: #64748b; font-size: .68rem; font-weight: 700;
|
||||
font-variant-numeric: tabular-nums; text-align: center;
|
||||
}
|
||||
.ez-name { font-weight: 700; font-size: .84rem; color: #0f172a; }
|
||||
.ez-name:hover { color: #0e7490; }
|
||||
.ez-sub { font-size: .68rem; color: #94a3b8; margin-top: .1rem; }
|
||||
|
||||
/* اعداد و شمارهها */
|
||||
.ez-num { font-variant-numeric: tabular-nums; }
|
||||
.ez-phone {
|
||||
direction: ltr; unicode-bidi: isolate;
|
||||
font-variant-numeric: tabular-nums; letter-spacing: .01em;
|
||||
}
|
||||
.ez-muted { color: #cbd5e1; }
|
||||
|
||||
.ez-badge {
|
||||
display: inline-block; padding: .1rem .45rem; border-radius: 999px;
|
||||
font-size: .68rem; font-weight: 700; white-space: nowrap; line-height: 1.6;
|
||||
}
|
||||
.ez-badge.danger { background: #fee2e2; color: #b91c1c; }
|
||||
.ez-badge.success { background: #dcfce7; color: #15803d; }
|
||||
.ez-badge.warning { background: #fef3c7; color: #b45309; }
|
||||
.ez-badge.mixed { background: #e0f2fe; color: #0369a1; }
|
||||
|
||||
/* تأخیر بهصورت چیپ (خوانا در یک نگاه) */
|
||||
.ez-late {
|
||||
display: inline-block; min-width: 4.4rem; padding: .1rem .4rem;
|
||||
border-radius: .3rem; font-size: .72rem; font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.ez-late.lv0 { background: #f8fafc; color: #94a3b8; }
|
||||
.ez-late.lv1 { background: #fffbeb; color: #b45309; }
|
||||
.ez-late.lv2 { background: #fef2f2; color: #dc2626; }
|
||||
.ez-late.lv3 { background: #fde8e8; color: #991b1b; }
|
||||
|
||||
/* آدرس: حداکثر دو خط (بدون شکستن چیدمان) */
|
||||
.ez-addr {
|
||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
||||
overflow: hidden; text-align: right; font-size: .78rem; color: #475569;
|
||||
}
|
||||
|
||||
/* ---------- حالت کارت (موبایل) ---------- */
|
||||
.ez-only-desktop { display: none !important; }
|
||||
|
||||
@media (max-width: 899px) {
|
||||
.ez-table thead { display: none; }
|
||||
.ez-table, .ez-table tbody, .ez-table tr, .ez-table td { display: block; width: 100%; }
|
||||
.ez-table tbody tr {
|
||||
display: flex; flex-wrap: wrap; align-items: baseline;
|
||||
background: #fff; border: 1px solid #e5e7eb; border-radius: .625rem;
|
||||
margin-bottom: .5rem; padding: .55rem .7rem;
|
||||
}
|
||||
.ez-table tbody tr:hover td { background: transparent; }
|
||||
.ez-table tbody td {
|
||||
flex: 1 0 100%; display: flex; flex-wrap: wrap; align-items: baseline;
|
||||
gap: .3rem; padding: .12rem 0; border: 0; text-align: right;
|
||||
}
|
||||
.ez-table tbody td::before {
|
||||
content: attr(data-label); flex: 0 0 6.5rem;
|
||||
font-size: .7rem; color: #94a3b8;
|
||||
}
|
||||
/* سرِ کارت: نام مشتری، بدون برچسب */
|
||||
.ez-table tbody td.ez-card-head {
|
||||
padding-bottom: .35rem; margin-bottom: .25rem;
|
||||
border-bottom: 1px dashed #eef2f6;
|
||||
}
|
||||
.ez-table tbody td.ez-card-head::before,
|
||||
.ez-table tbody td.ez-nolabel::before { content: none; }
|
||||
.ez-actions { flex: 1 0 100%; display: flex; gap: .35rem; margin-top: .4rem; }
|
||||
.ez-actions .button { margin: 0 !important; flex: 1 1 0; }
|
||||
.ez-addr { -webkit-line-clamp: 3; }
|
||||
.ez-legend { font-size: .7rem; }
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.ez-table thead { display: table-header-group; }
|
||||
.ez-table tbody { display: table-row-group; }
|
||||
.ez-table tr { display: table-row; }
|
||||
.ez-table td { display: table-cell; }
|
||||
.ez-table td::before { content: none; }
|
||||
.ez-only-desktop { display: table-cell !important; }
|
||||
.ez-only-mobile { display: none !important; }
|
||||
.ez-actions { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="ez-wrap">
|
||||
<div class="columns m-0">
|
||||
<div class="column is-12 p-0">
|
||||
{# ===== نوار آمار: هر عدد لینک فیلتر ===== #}
|
||||
<div class="ez-stats">
|
||||
<a href="?view=all&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat {% if view == 'all' %}is-active{% endif %}">
|
||||
<span class="ez-num">{{ counts.total }}</span>
|
||||
<span class="ez-lbl">کل معوق</span>
|
||||
</a>
|
||||
<a href="?view=uncoordinated&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat {% if view == 'uncoordinated' %}is-active{% endif %}">
|
||||
<span class="ez-num has-text-danger">{{ counts.uncoordinated }}</span>
|
||||
<span class="ez-lbl">بدون قرار</span>
|
||||
</a>
|
||||
<a href="?view=coordinated&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat {% if view == 'coordinated' %}is-active{% endif %}">
|
||||
<span class="ez-num has-text-success">{{ counts.coordinated }}</span>
|
||||
<span class="ez-lbl">با قرار</span>
|
||||
</a>
|
||||
<a href="?view=manual&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat {% if view == 'manual' %}is-active{% endif %}">
|
||||
<span class="ez-num has-text-warning-dark">{{ counts.manual }}</span>
|
||||
<span class="ez-lbl">قرار هماهنگی</span>
|
||||
</a>
|
||||
<a href="?view=scheduled&sort={{ sort }}{% if searchVal %}&searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}"
|
||||
class="ez-stat {% if view == 'scheduled' %}is-active{% endif %}">
|
||||
<span class="ez-num has-text-link">{{ counts.scheduled }}</span>
|
||||
<span class="ez-lbl">بازدید برنامهریزیشده</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>
|
||||
|
||||
{# ===== ابزارکها: جستجو و مرتبسازی ===== #}
|
||||
<div class="ez-toolbar">
|
||||
<a href="#" id="openSearchBox" class="button is-info is-outlined is-rounded is-small">
|
||||
جستجو{% if searchVal %}: «{{ searchVal }}»{% endif %}
|
||||
</a>
|
||||
|
||||
<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>
|
||||
</span>
|
||||
|
||||
{% if searchVal %}
|
||||
<a href="?view={{ view }}&sort={{ sort }}" class="button is-small is-light">حذف جستجو</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<table class="table has-text-centered is-bordered is-striped is-narrow is-hoverable is-fullwidth">
|
||||
<!-- Your table content -->
|
||||
<table class="table ez-table">
|
||||
<colgroup>
|
||||
<col style="width: 23%">
|
||||
<col style="width: 13%">
|
||||
<col style="width: 10%">
|
||||
<col style="width: 11%">
|
||||
<col style="width: 10%">
|
||||
<col style="width: 9%">
|
||||
<col style="width: 11%">
|
||||
<col style="width: 13%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr style="
|
||||
background: #33b5d3;
|
||||
">
|
||||
<th >ردیف</th>
|
||||
<th style="min-width: 200px;">نام و نام خانودگی</th>
|
||||
<th >آخرین بازدید</th>
|
||||
<th >تلفن</th>
|
||||
<th style="min-width: 400px;">آدرس</th>
|
||||
<tr>
|
||||
<th>نام و نام خانوادگی</th>
|
||||
<th>وضعیت قرار</th>
|
||||
<th>قرار هماهنگی</th>
|
||||
<th>بازدید برنامهریزیشده</th>
|
||||
<th>آخرین بازدید</th>
|
||||
<th>تأخیر</th>
|
||||
<th>تلفن</th>
|
||||
<th>آدرس</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for customer in customers %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>
|
||||
{# سرِ ردیف: چیپ شماره + نام (شمارهٔ ردیف دیگر ستون جداگانه ندارد) #}
|
||||
<td data-label="نام" class="ez-card-head" style="text-align: right;">
|
||||
<input class="is-hidden fid fidv-20" value="20">
|
||||
<a target="_blank" href="{% url 'admin_panel:customerAction' customer.id %}" class="tdvl name">
|
||||
{% if customer.name_family|length >= 2 %} {{ customer.name_family }} {% else %} نامعلوم {% endif %}
|
||||
<span class="ez-idx">{{ forloop.counter0|add:customers.start_index }}</span>
|
||||
<a target="_blank" href="{% url 'admin_panel:customerAction' customer.id %}" class="tdvl name ez-name">
|
||||
{% if customer.name_family|length >= 2 %}{{ customer.name_family }}{% else %}نامعلوم{% endif %}
|
||||
</a>
|
||||
{% if customer.idCode %}<div class="ez-sub">کد: {{ customer.idCode }}</div>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="tdvl lastView">
|
||||
{{ customer.last_bazdid_dt | toJalali }}
|
||||
</div>
|
||||
{% with appt=appointment_rows|row_for:customer.id %}
|
||||
<td data-label="وضعیت" class="ez-nolabel">
|
||||
{% if appt.manual and appt.scheduled or appt.manual and appt.coordination %}
|
||||
<span class="ez-badge mixed">قرار + بازدید</span>
|
||||
{% elif appt.manual %}
|
||||
<span class="ez-badge warning">قرار هماهنگی</span>
|
||||
{% elif appt.scheduled or appt.coordination %}
|
||||
<span class="ez-badge success">بازدید برنامهریزیشده</span>
|
||||
{% else %}
|
||||
<span class="ez-badge danger">بدون قرار</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td data-label="قرار هماهنگی" class="ez-num ez-nowrap">
|
||||
{% if appt.manual %}{{ appt.manual|toJalali }}{% else %}<span class="ez-muted">—</span>{% endif %}
|
||||
</td>
|
||||
<td data-label="بازدید برنامه" class="ez-num ez-nowrap">
|
||||
{% if appt.scheduled %}{{ appt.scheduled|toJalali }}
|
||||
{% elif appt.coordination %}{{ appt.coordination|toJalali }}<div class="ez-sub">در انتظار تماس</div>
|
||||
{% else %}<span class="ez-muted">—</span>{% endif %}
|
||||
</td>
|
||||
<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>
|
||||
<td data-label="تأخیر" class="ez-nowrap">
|
||||
{% if appt.overdue_days >= 180 %}
|
||||
<span class="ez-late lv3">{{ appt.overdue_days }} روز</span>
|
||||
{% elif appt.overdue_days >= 90 %}
|
||||
<span class="ez-late lv2">{{ appt.overdue_days }} روز</span>
|
||||
{% elif appt.overdue_days >= 30 %}
|
||||
<span class="ez-late lv1">{{ appt.overdue_days }} روز</span>
|
||||
{% else %}
|
||||
<span class="ez-late lv0">{{ appt.overdue_days }} روز</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endwith %}
|
||||
|
||||
<td>
|
||||
<div class="tdvl mobile_1">
|
||||
{{ customer.phone1 }}
|
||||
</div>
|
||||
<div class="tdvl is-hidden mobile_2">
|
||||
09384999655
|
||||
</div>
|
||||
<div class="tdvl is-hidden mobile_3">
|
||||
{{ customer.phone2 }}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="tdvl address">
|
||||
{{ customer.address }}
|
||||
<td data-label="تلفن" class="ez-nowrap">
|
||||
<span class="tdvl mobile_1 ez-phone">
|
||||
{% if customer.phone1 %}{{ customer.phone1 }}{% else %}<span class="ez-muted">—</span>{% endif %}
|
||||
</span>
|
||||
<span class="tdvl is-hidden mobile_2">{{ customer.phone2 }}</span>
|
||||
<span class="tdvl is-hidden mobile_3">{{ customer.phone3 }}</span>
|
||||
{# دکمههای اقدام سریع — فقط موبایل #}
|
||||
<div class="ez-actions">
|
||||
{% if customer.phone1 %}
|
||||
<a href="tel:{{ customer.phone1 }}" class="button is-success is-small">تماس</a>
|
||||
{% endif %}
|
||||
<a target="_blank" href="{% url 'admin_panel:customerAction' customer.id %}" class="button is-info is-small">ثبت اقدام</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<td data-label="آدرس">
|
||||
<div class="tdvl address ez-addr" title="{{ customer.address }}">{{ customer.address }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="8" class="has-text-centered py-5">
|
||||
<span class="has-text-grey">موردی در این نما پیدا نشد.</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="">
|
||||
{% if customers.has_previous %}
|
||||
<a class="button is-danger" href="?{% if searchVal %}searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}&page={{ customers.previous_page_number }}">صفحه قبل</a>
|
||||
{% endif %}
|
||||
|
||||
{% if customers.has_next %}
|
||||
<a class="button is-danger" href="?{% if searchVal %}searchVal={{ searchVal }}&searchOn={{ searchOn }}{% endif %}&page={{ customers.next_page_number }}">صفحه بعد</a>
|
||||
{# ===== صفحهبندی ===== #}
|
||||
<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>
|
||||
{% else %}<span></span>{% endif %}
|
||||
|
||||
{% endif %}
|
||||
<span class="is-size-7 has-text-grey">
|
||||
صفحهٔ {{ customers.number }} از {{ customers.paginator.num_pages }} ·
|
||||
{{ customers.paginator.count }} مورد
|
||||
</span>
|
||||
|
||||
</div>
|
||||
{% 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>
|
||||
{% 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" placeholder="">
|
||||
<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">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="searchOn">
|
||||
<!--
|
||||
<option value="name">نام و نام خانوادگی</option>
|
||||
<option value="code">کدمشتری</option>
|
||||
<option value="phone">تلفن</option> !-->
|
||||
<option value="address">آدرس</option>
|
||||
<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" id="searchbtn" value="جستجو مشتری" type="submit">
|
||||
<input class="button is-success is-fullwidth" id="searchbtn" value="جستجو مشتری" type="submit">
|
||||
</div>
|
||||
<!-- -->
|
||||
</form>
|
||||
|
||||
|
||||
@@ -112,109 +382,17 @@
|
||||
<button class="modal-close is-large closeSearch" aria-label="close"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal BazdidF">
|
||||
<div class="modal-background closeBazdidF"></div>
|
||||
<div class="modal-content">
|
||||
<div class="columns is-mobile is-multiline">
|
||||
|
||||
<div class="field column is-12-desktop is-12-mobile m-0">
|
||||
<label class="label">نام ونام خانوادگی</label>
|
||||
<div class="control">
|
||||
<input class="input rf_name" id="bz_name" type="text" placeholder="نام نام خانوادگی">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-4-desktop is-12-mobile m-0">
|
||||
<label class="label">تلفن همراه</label>
|
||||
<div class="control">
|
||||
<input class="input rf_mobile" id="phone-1" type="text" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-4-desktop is-12-mobile m-0">
|
||||
<label class="label">تاریخ</label>
|
||||
<div class="control">
|
||||
<input name="bazdidDateTime" id="persianDateP" class="input bz_DateTime" type="text" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="field column is-4-desktop is-12-mobile m-0">
|
||||
<label class="label">توسط</label>
|
||||
<div class="select">
|
||||
<select>
|
||||
<option>کدام خدمات؟</option>
|
||||
<option>خدمات 1</option>
|
||||
<option>خدمات 2</option>
|
||||
<option>خدمات 3</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-4-desktop is-12-mobile m-0">
|
||||
<label class="label">زمان مراجعه</label>
|
||||
<div class="select">
|
||||
<select>
|
||||
<option>زمان را انتخاب کنید</option>
|
||||
<option>صبح</option>
|
||||
<option>ظهر</option>
|
||||
<option>بعد از ظهر</option>
|
||||
<option>غروب</option>
|
||||
<option>شب</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-8-desktop is-12-mobile m-0">
|
||||
<label class="label">توضیحات</label>
|
||||
<div class="control">
|
||||
<textarea class="textarea" placeholder="توضیحات"></textarea> </div>
|
||||
</div>
|
||||
|
||||
<div class="field column is-12-desktop is-12-mobile m-0">
|
||||
<input class="button is-success" id="editCS" value="ایجاد بازدید" type="submit">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<button class="modal-close is-large closeBazdidF" aria-label="close"></button>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block jsEnd %}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
kamaDatepicker('persianDateP', { buttonsColor: "red", forceFarsiDigits: true });
|
||||
|
||||
$(".closeBazdidF").click(function(){
|
||||
$(".BazdidF").removeClass("is-active")
|
||||
$("#openSearchBox").click(function(e) {
|
||||
e.preventDefault();
|
||||
$(".SearchBox").addClass("is-active");
|
||||
});
|
||||
|
||||
$("#openSearchBox").click(function(){
|
||||
$(".SearchBox").addClass("is-active")
|
||||
$(".closeSearch").click(function() {
|
||||
$(".SearchBox").removeClass("is-active");
|
||||
});
|
||||
|
||||
$(".closeSearch").click(function(){
|
||||
$(".SearchBox").removeClass("is-active")
|
||||
});
|
||||
|
||||
$(".openRow").click(function(){
|
||||
var id = $(this).parent().parent().find('.fid').val().trim();
|
||||
var name = $(this).parent().parent().find('.name').text().trim();
|
||||
var mobile_1 = $(this).parent().parent().find('.mobile_1').text().trim();
|
||||
|
||||
var address = $(this).parent().parent().find('.address').text().trim();
|
||||
//alert(id)
|
||||
$(".BazdidF").find('#bz_name').val(name);
|
||||
$(".BazdidF").find('#phone-1').val(mobile_1);
|
||||
|
||||
//$("#bedehiStatus").val('وضعیت')
|
||||
|
||||
$(".BazdidF").addClass("is-active")
|
||||
});
|
||||
} );
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
Reference in new issue
Block a user