030bbc98fd
Шаблоны/ручное создание, access_projects, сид «Открытие аптеки». Плюс SILO/S3 для Django media. Co-authored-by: Cursor <cursoragent@cursor.com>
128 lines
9.6 KiB
HTML
128 lines
9.6 KiB
HTML
{% load i18n %}
|
|
<div class="page-content">
|
|
<div style="display:flex; align-items:flex-start; justify-content:space-between; margin-bottom:1.25rem; gap:0.75rem; flex-wrap:wrap;">
|
|
<div>
|
|
<h1 style="font-size:1.25rem; font-weight:500; margin:0;">{% trans "Проекты" %}</h1>
|
|
<p style="font-size:0.875rem; color:var(--color-muted-foreground); margin:0.25rem 0 0;">
|
|
{% trans "Межотдельские проекты со шагами и задачами (например, открытие аптеки)" %}
|
|
</p>
|
|
</div>
|
|
<button type="button" class="btn btn-primary" onclick="document.getElementById('project-create').showModal()">
|
|
{% trans "Новый проект" %}
|
|
</button>
|
|
</div>
|
|
|
|
{% if ug_message %}
|
|
<div style="margin-bottom:1rem; padding:0.625rem 0.875rem; border-radius:0.5rem; font-size:0.8125rem; color:#137333; background:rgba(19,115,51,0.1); border:1px solid rgba(19,115,51,0.25);">{{ ug_message }}</div>
|
|
{% endif %}
|
|
{% if ug_error %}
|
|
<div style="margin-bottom:1rem; padding:0.625rem 0.875rem; border-radius:0.5rem; font-size:0.8125rem; color:#d63333; background:rgba(214,51,51,0.1); border:1px solid rgba(214,51,51,0.25);">{{ ug_error }}</div>
|
|
{% endif %}
|
|
|
|
<div style="display:flex; gap:0.25rem; margin-bottom:1rem; background:var(--color-muted); border-radius:var(--radius); padding:0.25rem; width:fit-content; flex-wrap:wrap;">
|
|
{% with base="display:inline-flex; padding:0.375rem 0.75rem; border-radius:calc(var(--radius) - 2px); font-size:0.8125rem; font-weight:500; text-decoration:none;" %}
|
|
<a href="{% url 'projects' %}" hx-get="{% url 'projects' %}" hx-target="#main-content" hx-push-url="{% url 'projects' %}" hx-indicator="#loader"
|
|
style="{{ base }} {% if not active_status %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}color:var(--color-muted-foreground);{% endif %}">{% trans "Все" %}</a>
|
|
<a href="{% url 'projects' %}?status=draft" hx-get="{% url 'projects' %}?status=draft" hx-target="#main-content" hx-push-url="{% url 'projects' %}?status=draft" hx-indicator="#loader"
|
|
style="{{ base }} {% if active_status == 'draft' %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}color:var(--color-muted-foreground);{% endif %}">{% trans "Черновики" %}</a>
|
|
<a href="{% url 'projects' %}?status=active" hx-get="{% url 'projects' %}?status=active" hx-target="#main-content" hx-push-url="{% url 'projects' %}?status=active" hx-indicator="#loader"
|
|
style="{{ base }} {% if active_status == 'active' %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}color:var(--color-muted-foreground);{% endif %}">{% trans "Активные" %}</a>
|
|
<a href="{% url 'projects' %}?status=done" hx-get="{% url 'projects' %}?status=done" hx-target="#main-content" hx-push-url="{% url 'projects' %}?status=done" hx-indicator="#loader"
|
|
style="{{ base }} {% if active_status == 'done' %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}color:var(--color-muted-foreground);{% endif %}">{% trans "Завершённые" %}</a>
|
|
{% endwith %}
|
|
</div>
|
|
|
|
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); overflow:hidden;">
|
|
{% for p in projects %}
|
|
<a href="{% url 'project_detail' p.pk %}"
|
|
hx-get="{% url 'project_detail' p.pk %}" hx-target="#main-content" hx-push-url="{% url 'project_detail' p.pk %}" hx-indicator="#loader"
|
|
class="li-hover" style="display:block; padding:0.875rem 1rem; text-decoration:none; color:inherit; {% if not forloop.last %}border-bottom:1px solid var(--color-border);{% endif %}">
|
|
<div style="display:flex; justify-content:space-between; gap:1rem; align-items:flex-start; flex-wrap:wrap;">
|
|
<div style="min-width:0; flex:1;">
|
|
<div style="font-size:0.9375rem; font-weight:500;">{{ p.title }}</div>
|
|
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.2rem;">
|
|
{% if p.pharmacy %}{{ p.pharmacy }} · {% endif %}
|
|
{% if p.owner %}{{ p.owner.get_full_name }} · {% endif %}
|
|
{{ p.get_status_display }}
|
|
{% if p.due_date %} · {% trans "до" %} {{ p.due_date }}{% endif %}
|
|
</div>
|
|
</div>
|
|
<div style="min-width:8rem;">
|
|
<div style="font-size:0.7rem; color:var(--color-muted-foreground); margin-bottom:0.25rem;">{{ p.done_count }}/{{ p.total_count }} · {{ p.pct }}%</div>
|
|
<div style="height:0.35rem; background:var(--color-muted); border-radius:999px; overflow:hidden;">
|
|
<div style="height:100%; width:{{ p.pct }}%; background:var(--color-primary);"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
{% empty %}
|
|
<div style="padding:2rem; text-align:center; color:var(--color-muted-foreground); font-size:0.875rem;">
|
|
{% trans "Проектов пока нет. Создайте из шаблона или вручную." %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<dialog id="project-create" style="border:1px solid var(--color-border); border-radius:0.75rem; padding:0; max-width:32rem; width:calc(100% - 2rem); background:var(--color-card); color:var(--color-foreground);">
|
|
<form method="post" action="{% url 'project_create' %}" style="padding:1.25rem; margin:0;">
|
|
{% csrf_token %}
|
|
<h2 style="font-size:1rem; font-weight:500; margin:0 0 1rem;">{% trans "Новый проект" %}</h2>
|
|
|
|
<label style="display:block; font-size:0.75rem; margin-bottom:0.35rem;">{% trans "Режим" %}</label>
|
|
<select name="mode" id="project-mode" class="input" style="width:100%; margin-bottom:0.75rem;" onchange="document.getElementById('tpl-block').style.display=this.value==='template'?'block':'none'; document.getElementById('manual-block').style.display=this.value==='manual'?'block':'none';">
|
|
<option value="template">{% trans "Из шаблона" %}</option>
|
|
<option value="manual">{% trans "Вручную" %}</option>
|
|
</select>
|
|
|
|
<label style="display:block; font-size:0.75rem; margin-bottom:0.35rem;">{% trans "Название" %}</label>
|
|
<input type="text" name="title" class="input" style="width:100%; margin-bottom:0.75rem;" placeholder="{% trans 'Открытие аптеки №…' %}">
|
|
|
|
<div id="tpl-block">
|
|
<label style="display:block; font-size:0.75rem; margin-bottom:0.35rem;">{% trans "Шаблон" %}</label>
|
|
<select name="template_id" class="input" style="width:100%; margin-bottom:0.75rem;">
|
|
<option value="">{% trans "Выберите…" %}</option>
|
|
{% for t in templates %}
|
|
<option value="{{ t.id }}">{{ t.name }} ({{ t.default_duration_days }} {% trans "дн." %})</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<div id="manual-block" style="display:none;">
|
|
<p style="font-size:0.75rem; color:var(--color-muted-foreground); margin:0 0 0.5rem;">
|
|
{% trans "Шаги: название, отдел, задачи (по одной на строку). Можно добавить больше шагов на карточке." %}
|
|
</p>
|
|
{% for i in "12" %}
|
|
<div style="border:1px solid var(--color-border); border-radius:0.5rem; padding:0.75rem; margin-bottom:0.5rem;">
|
|
<input type="text" name="step_title" class="input" style="width:100%; margin-bottom:0.35rem;" placeholder="{% trans 'Шаг' %} {{ forloop.counter }}">
|
|
<select name="step_department_id" class="input" style="width:100%; margin-bottom:0.35rem;">
|
|
<option value="">{% trans "Отдел…" %}</option>
|
|
{% for d in departments %}
|
|
<option value="{{ d.id }}">{{ d.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<textarea name="step_items" class="input" rows="2" style="width:100%;" placeholder="{% trans 'Задачи, каждая с новой строки' %}"></textarea>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<label style="display:block; font-size:0.75rem; margin-bottom:0.35rem;">{% trans "Описание" %}</label>
|
|
<textarea name="description" class="input" rows="2" style="width:100%; margin-bottom:0.75rem;"></textarea>
|
|
|
|
<div style="display:flex; gap:0.5rem; margin-bottom:1rem; flex-wrap:wrap;">
|
|
<div style="flex:1; min-width:8rem;">
|
|
<label style="display:block; font-size:0.75rem; margin-bottom:0.35rem;">{% trans "Старт" %}</label>
|
|
<input type="date" name="start_date" class="input" style="width:100%;">
|
|
</div>
|
|
<div style="flex:1; min-width:8rem;">
|
|
<label style="display:block; font-size:0.75rem; margin-bottom:0.35rem;">{% trans "Срок" %}</label>
|
|
<input type="date" name="due_date" class="input" style="width:100%;">
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display:flex; gap:0.5rem; justify-content:flex-end;">
|
|
<button type="button" class="btn btn-secondary" onclick="this.closest('dialog').close()">{% trans "Отмена" %}</button>
|
|
<button type="submit" class="btn btn-primary">{% trans "Создать" %}</button>
|
|
</div>
|
|
</form>
|
|
</dialog>
|