fix UI UX

This commit is contained in:
javad committed 2026-10-06 12:08:16 +03:30
1 parent 1cbbbbd0dc
commit d99e47ecce
11 files changed
+333 -32

No files matched your search

+31 -14
View File
@@ -1,20 +1,37 @@
{% extends 'base.html' %}{% load static %}
{% extends 'payments/base.html' %}{% load static %}
{% block title %}{{ page_title }}{% endblock %}
{% block extra_head %}{{ block.super }}<link rel="stylesheet" href="{% static 'css/customer-profile.css' %}?v={{ static_asset_version }}">{% endblock %}
{% block content %}
<div class="page-head"><div><p class="eyebrow">تنظیمات حساب</p><h1>پروفایل من</h1><p>اطلاعات شما به کارشناس کمک می‌کند پاسخ دقیق‌تری ارائه کند.</p></div><a class="nav-link" href="{% url 'tickets:list' %}">بازگشت به تیکت‌ها</a></div>
<section class="card form-card">
<div class="badge" dir="ltr">{{ user.mobile }}</div>
<form method="post" class="mt-6" data-disable-on-submit>{% csrf_token %}{{ form.non_field_errors }}
<div class="grid gap-4 sm:grid-cols-2"><div class="field">{{ form.first_name.label_tag }}{{ form.first_name }}{{ form.first_name.errors }}</div><div class="field">{{ form.last_name.label_tag }}{{ form.last_name }}{{ form.last_name.errors }}</div></div>
<div class="field">{{ form.customer_type.label_tag }}{{ form.customer_type }}{{ form.customer_type.errors }}</div>
<section class="location-fields" data-location-picker data-locations-url="{% static 'data/iran-locations.json' %}">
<div class="location-heading"><div><h3>موقعیت پیش‌فرض</h3><p>اختیاری است؛ در تیکت‌های جدید به‌صورت خودکار پیشنهاد می‌شود.</p></div><span>اختیاری</span></div>
<div class="grid gap-4 sm:grid-cols-2"><div class="field">{{ form.province.label_tag }}{{ form.province }}<datalist id="profile-province-options" data-province-options></datalist>{{ form.province.errors }}</div><div class="field">{{ form.city.label_tag }}{{ form.city }}<datalist id="profile-city-options" data-city-options></datalist>{{ form.city.errors }}</div></div>
<p class="location-hint" data-location-hint>نام استان را جست‌وجو و انتخاب کنید.</p>
<section class="chaharsu customer-profile" aria-labelledby="profile-title">
<header class="chaharsu-heading">
<a class="profile-breadcrumb" href="{% url 'payments:home' %}">خدمات چهارسو</a>
<div class="profile-heading"><span class="service-icon">{% include 'payments/_icon.html' with name='user' %}</span><div><h1 id="profile-title">پروفایل من</h1><p>اطلاعات شما به کارشناس کمک می‌کند پاسخ دقیق‌تری ارائه کند.</p></div></div>
</header>
<form method="post" class="pay-form customer-profile-form" data-disable-on-submit>{% csrf_token %}
{% if form.errors %}<div class="pay-errors" role="alert"><p>اطلاعات مشخص‌شده را بررسی و دوباره ذخیره کنید.</p>{{ form.non_field_errors }}</div>{% endif %}
<section class="pay-card" aria-labelledby="profile-personal-title">
<div class="profile-card-heading"><h2 id="profile-personal-title">اطلاعات حساب</h2><span class="profile-mobile"><span>شماره همراه</span><bdi>{{ user.mobile }}</bdi></span></div>
<div class="profile-field-grid">
<div class="pay-field">{{ form.first_name.label_tag }}{{ form.first_name }}{{ form.first_name.errors }}</div>
<div class="pay-field">{{ form.last_name.label_tag }}{{ form.last_name }}{{ form.last_name.errors }}</div>
<div class="pay-field">{{ form.customer_type.label_tag }}{{ form.customer_type }}{{ form.customer_type.errors }}</div>
</div>
</section>
<div class="field">{{ form.password.label_tag }}{{ form.password }}{% if form.password.help_text %}<small class="muted">{{ form.password.help_text }}</small>{% endif %}{{ form.password.errors }}</div>
<button type="submit">ذخیره تغییرات</button>
<section class="pay-card" data-location-picker data-locations-url="{% static 'data/iran-locations.json' %}?v={{ static_asset_version }}" aria-labelledby="profile-location-title">
<h2 id="profile-location-title">موقعیت پیش‌فرض</h2>
<p class="profile-guidance">اختیاری است؛ در درخواست‌های جدید به‌صورت خودکار پیشنهاد می‌شود.</p>
<div class="profile-field-grid">
<div class="pay-field">{{ form.province.label_tag }}{{ form.province }}<datalist id="profile-province-options" data-province-options></datalist>{{ form.province.errors }}</div>
<div class="pay-field">{{ form.city.label_tag }}{{ form.city }}<datalist id="profile-city-options" data-city-options></datalist>{{ form.city.errors }}</div>
</div>
<p class="profile-guidance" data-location-hint role="status">نام استان را جست‌وجو و انتخاب کنید.</p>
</section>
<section class="pay-card" aria-labelledby="profile-password-title">
<h2 id="profile-password-title">رمز عبور</h2>
<div class="pay-field">{{ form.password.label_tag }}{{ form.password }}{% if form.password.help_text %}<p class="profile-guidance" id="{{ form.password.auto_id }}_helptext">{{ form.password.help_text }}</p>{% endif %}{{ form.password.errors }}</div>
</section>
<div class="profile-actions"><button class="pay-button" type="submit">ذخیره تغییرات</button><a class="pay-button secondary" href="{% url 'tickets:list' %}">بازگشت به درخواست‌ها</a></div>
</form>
</section>
<script src="{% static 'js/location-picker.js' %}?v={{ static_asset_version }}"></script>
{% endblock %}
{% block extra_scripts %}<script defer src="{% static 'js/location-picker.js' %}?v={{ static_asset_version }}"></script>{% endblock %}
+2 -1
View File
@@ -12,6 +12,7 @@
<link rel="stylesheet" href="{% static 'css/tailwind.css' %}?v={{ static_asset_version }}">
<link rel="stylesheet" href="{% static 'css/operations.css' %}?v={{ static_asset_version }}">
<link rel="stylesheet" href="{% static 'css/dispatches.css' %}?v={{ static_asset_version }}">
{% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' or financial_page or request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name == 'list' or request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name == 'new' %}<link rel="stylesheet" href="{% static 'css/customer-dock.css' %}?v={{ static_asset_version }}">{% endif %}
<script defer src="{% static 'vendor/htmx-2.0.3.min.js' %}?v={{ static_asset_version }}"></script><script defer src="{% static 'vendor/alpine-3.14.8.min.js' %}?v={{ static_asset_version }}"></script>
{% block extra_head %}{% endblock %}
</head>
@@ -65,7 +66,7 @@
</nav>{% endblock %}
</div>
{% elif user.is_authenticated %}
{% if financial_page %}<nav class="mobile-dock customer-mobile-dock chaharsu-dock" aria-label="دسترسی سریع مشتری"><a href="{% url 'payments:home' %}" {% if request.resolver_match.url_name == 'home' %}class="active" aria-current="page"{% endif %}><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3h7v7H3V3Zm11 0h7v7h-7V3ZM3 14h7v7H3v-7Zm11 0h7v7h-7v-7Z"/></svg>خدمات</a><a href="{% url 'tickets:list' %}"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5h16v12H9l-5 4V5Zm4 4h8m-8 4h5"/></svg>درخواست‌ها</a><a href="{% url 'accounts:profile' %}"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M16 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0ZM4 21v-2a8 8 0 0 1 16 0v2"/></svg>پروفایل</a></nav>{% else %} <nav class="mobile-dock customer-mobile-dock" aria-label="دسترسی سریع مشتری"><a class="{% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}active{% endif %}" href="{% url 'tickets:list' %}" {% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}aria-current="page"{% endif %}><span class="dock-icon">◎</span>درخواست‌ها</a><a class="{% if request.resolver_match.url_name == 'new' %}active{% endif %}" href="{% url 'tickets:new' %}" {% if request.resolver_match.url_name == 'new' %}aria-current="page"{% endif %}><span class="dock-icon">+</span>درخواست جدید</a><a class="{% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}active{% endif %}" href="{% url 'accounts:profile' %}" {% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}aria-current="page"{% endif %}><span class="dock-icon">○</span>پروفایل</a><form method="post" action="{% url 'accounts:logout' %}">{% csrf_token %}<button type="submit"><span class="dock-icon">←</span>خروج</button></form></nav>{% endif %}
{% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' or financial_page or request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name == 'list' or request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name == 'new' %}{% include 'tickets/_customer_dock.html' %}{% else %} <nav class="mobile-dock customer-mobile-dock" aria-label="دسترسی سریع مشتری"><a class="{% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}active{% endif %}" href="{% url 'tickets:list' %}" {% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}aria-current="page"{% endif %}><span class="dock-icon">◎</span>درخواست‌ها</a><a class="{% if request.resolver_match.url_name == 'new' %}active{% endif %}" href="{% url 'tickets:new' %}" {% if request.resolver_match.url_name == 'new' %}aria-current="page"{% endif %}><span class="dock-icon">+</span>درخواست جدید</a><a class="{% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}active{% endif %}" href="{% url 'accounts:profile' %}" {% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}aria-current="page"{% endif %}><span class="dock-icon">○</span>پروفایل</a><form method="post" action="{% url 'accounts:logout' %}">{% csrf_token %}<button type="submit"><span class="dock-icon">←</span>خروج</button></form></nav>{% endif %}
{% endif %}
{% block pwa_install_prompt %}{% endblock %}
<script src="{% static 'js/voice-recorder.js' %}?v={{ static_asset_version }}"></script><script src="{% static 'js/ui.js' %}?v={{ static_asset_version }}"></script><script src="{% static 'js/chat-coach.js' %}?v={{ static_asset_version }}"></script>
+14
View File
@@ -0,0 +1,14 @@
<nav class="mobile-dock customer-mobile-dock chaharsu-dock" aria-label="دسترسی سریع مشتری">
<a href="{% url 'payments:home' %}" {% if request.resolver_match.namespace == 'payments' and request.resolver_match.url_name == 'home' %}class="active" aria-current="page"{% endif %}>
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3h7v7H3V3Zm11 0h7v7h-7V3ZM3 14h7v7H3v-7Zm11 0h7v7h-7v-7Z"/></svg>
خدمات
</a>
<a href="{% url 'tickets:list' %}" {% if request.resolver_match.namespace == 'tickets' %}class="active" {% if request.resolver_match.url_name == 'list' %}aria-current="page"{% else %}aria-current="true"{% endif %}{% endif %}>
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5h16v12H9l-5 4V5Zm4 4h8m-8 4h5"/></svg>
درخواست‌ها
</a>
<a href="{% url 'accounts:profile' %}" {% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}class="active" aria-current="page"{% endif %}>
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M16 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0ZM4 21v-2a8 8 0 0 1 16 0v2"/></svg>
پروفایل
</a>
</nav>
+27 -17
View File
@@ -1,29 +1,39 @@
{% extends 'base.html' %}{% load jalali %}
{% extends 'payments/base.html' %}{% load static jalali %}
{% block title %}{{ page_title }}{% endblock %}
{% block extra_head %}{{ block.super }}<link rel="stylesheet" href="{% static 'css/customer-tickets.css' %}?v={{ static_asset_version }}">{% endblock %}
{% block content %}
{% if site_branding.customer_tickets_hero_enabled %}<section class="hero-panel">
<p class="page-kicker">{{ site_branding.customer_tickets_hero_eyebrow }}</p>
<h1>{{ site_branding.customer_tickets_hero_heading|linebreaksbr }}</h1>
<p>{{ site_branding.customer_tickets_hero_body|linebreaksbr }}</p>
<div class="hero-actions">
<a class="button" href="{% url 'tickets:new' %}"><span>+</span> ثبت درخواست جدید</a>
<a class="button hero-history-button" href="#recent-requests"><span aria-hidden="true">↓</span> درخواست‌های قبلی</a>
<section class="chaharsu customer-tickets" aria-labelledby="customer-tickets-title">
<header class="chaharsu-heading"><a class="tickets-breadcrumb" href="{% url 'payments:home' %}">خدمات چهارسو</a><h1 id="customer-tickets-title">درخواست‌های من</h1><p>درخواست‌ها و پاسخ کارشناسان را از اینجا پیگیری کنید.</p></header>
{% if site_branding.customer_tickets_hero_enabled %}<section class="expert-service tickets-intro">
{% if site_branding.customer_tickets_hero_eyebrow %}<p class="tickets-intro-kicker">{{ site_branding.customer_tickets_hero_eyebrow }}</p>{% endif %}
<div class="expert-service-head">
<span class="service-icon">{% include 'payments/_icon.html' with name='chat' %}</span>
<h2>{{ site_branding.customer_tickets_hero_heading|linebreaksbr }}</h2>
<p>{{ site_branding.customer_tickets_hero_body|linebreaksbr }}</p>
</div>
<div class="service-actions">
<a class="pay-button light" href="{% url 'tickets:new' %}">{% include 'payments/_icon.html' with name='plus' %}ثبت درخواست جدید</a>
<a class="pay-button outline-light" href="#recent-requests">{% include 'payments/_icon.html' with name='history' %}درخواست‌های قبلی</a>
</div>
</section>{% endif %}
{% if missing_profile_fields %}<aside class="profile-completion-notice" role="note"><span class="profile-completion-icon" aria-hidden="true">◎</span><div><h2>تکمیل پروفایل، برای پیگیری دقیق‌تر</h2><p>مشتری گرامی، اطلاعات <b>{{ missing_profile_fields|join:'، ' }}</b> در پروفایل شما تکمیل نشده است. ثبت این اطلاعات اختیاری است؛ بااین‌حال توصیه می‌کنیم پیش از ثبت درخواست، آن‌ها را وارد کنید تا کارشناسان فروش بتوانند دقیق‌تر و سریع‌تر راهنمایی‌تان کنند.</p><div class="profile-completion-actions"><a class="button" href="{% url 'accounts:profile' %}">تکمیل پروفایل</a><a href="{% url 'tickets:new' %}">فعلاً ثبت درخواست را ادامه می‌دهم</a></div></div></aside>{% endif %}
<div class="page-head" id="recent-requests">
<div><p class="page-kicker">پیگیری‌ها</p><h2>درخواست‌های اخیر شما</h2></div>
<span class="muted">{{ tickets|length }} مورد</span>
{% if missing_profile_fields %}<aside class="tickets-profile-note" role="note"><span class="service-icon">{% include 'payments/_icon.html' with name='user' %}</span><div><h2>تکمیل پروفایل، برای پیگیری دقیق‌تر</h2><p>اطلاعات <b>{{ missing_profile_fields|join:'، ' }}</b> در پروفایل شما تکمیل نشده است. تکمیل آن‌ها اختیاری است و به راهنمایی دقیق‌تر کارشناسان کمک می‌کند.</p><div class="tickets-profile-actions"><a class="pay-button secondary" href="{% url 'accounts:profile' %}">تکمیل پروفایل</a><a class="tickets-text-link" href="{% url 'tickets:new' %}">فعلاً ثبت درخواست را ادامه می‌دهم</a></div></div></aside>{% endif %}
<div class="customer-list-heading" id="recent-requests">
<h2>درخواست‌های اخیر شما</h2>
<span>{{ tickets|length }} مورد</span>
</div>
<div class="ticket-grid">
<div class="tickets-list-grid">
{% for ticket in tickets %}
<a class="ticket-card" href="{% url 'tickets:detail' ticket.public_id %}">
<div><div class="ticket-card-top"><span class="ticket-number" dir="ltr">{{ ticket.ticket_number }}</span><span class="badge">{{ ticket.get_status_display }}</span></div><h2>{{ ticket.subject }}</h2></div>
<div class="ticket-meta"><div><small>{{ ticket.category }}</small><div class="expert-line">{{ ticket.assigned_expert_name }}</div></div><small>{{ ticket.last_activity_at|jalali_datetime }}</small></div>
<a class="tickets-list-card" href="{% url 'tickets:detail' ticket.public_id %}">
<div class="tickets-card-top"><span class="tickets-status">{{ ticket.get_status_display }}</span><bdi class="tickets-number">{{ ticket.ticket_number }}</bdi></div>
<h3>{{ ticket.subject }}</h3>
<div class="tickets-card-meta"><span>{{ ticket.category }}</span><span>کارشناس: {{ ticket.assigned_expert_name }}</span><time datetime="{{ ticket.last_activity_at|date:'c' }}">{{ ticket.last_activity_at|jalali_datetime }}</time></div>
<span class="tickets-card-link">مشاهده و پیگیری{% include 'payments/_icon.html' with name='arrow' %}</span>
</a>
{% empty %}
<div class="empty"><div class="empty-icon">✦</div><h2>هنوز درخواستی ثبت نشده</h2><p class="muted">اولین گفت‌وگوی خود را با تیم فروش آغاز کنید.</p><a class="button" href="{% url 'tickets:new' %}">ثبت اولین درخواست</a></div>
<div class="pay-card customer-empty tickets-empty">{% include 'payments/_icon.html' with name='chat' %}<h3>هنوز درخواستی ثبت نشده</h3><p>اولین گفت‌وگوی خود را با تیم فروش آغاز کنید.</p><a class="pay-button" href="{% url 'tickets:new' %}">{% include 'payments/_icon.html' with name='plus' %}ثبت اولین درخواست</a></div>
{% endfor %}
</div>
</section>
{% endblock %}
{% block extra_scripts %}{% endblock %}
{% block pwa_install_prompt %}<aside class="pwa-install" data-pwa-install hidden><img class="pwa-install-icon" src="{{ pwa_icon_url }}?v={{ static_asset_version }}-{{ branding_version }}" alt="" width="64" height="64"><div class="pwa-install-copy"><b>{{ site_branding.pwa_install_label }}</b><small data-pwa-help role="status">{{ site_branding.pwa_install_help }}</small></div><div class="pwa-install-actions"><button type="button" data-pwa-dismiss>بعداً</button><button type="button" class="primary" data-pwa-accept>نصب</button></div></aside>{% endblock %}