feat: admin panel enrichment

This commit is contained in:
mohamad
2026-07-19 14:31:28 +03:30
parent d8d7819eca
commit 1042fba121
77 changed files with 4616 additions and 2 deletions
+74
View File
@@ -0,0 +1,74 @@
{% extends "base.html" %}
{% block title %}{{ brief.title }}{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="brief-heading">
<div class="container">
<div class="page-hero-content page-hero-content--row">
<div>
{% if brief.category %}<div class="section-badge">{{ brief.get_category_display }}</div>{% endif %}
<h1 class="page-hero-title" id="brief-heading">{{ brief.title }}</h1>
<p class="page-hero-subtitle">
<span class="status-pill status-pill--{{ brief.status }}">{{ brief.get_status_display }}</span>
· Submitted {{ brief.submitted_at|date:"M j, Y" }}
</p>
</div>
<div class="portal-actions">
<a href="{% url 'projects:dashboard' %}" class="btn-ghost">Back to list</a>
{% if brief.is_editable_by_client %}
<a href="{% url 'projects:edit' pk=brief.pk %}" class="btn-primary">Edit brief</a>
{% endif %}
</div>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="portal-detail-grid">
<div class="glass-card portal-card fade-in">
<h2 class="portal-section-title">Overview</h2>
<dl class="portal-meta-list">
{% if brief.budget_range %}<div><dt>Budget</dt><dd>{{ brief.get_budget_range_display }}</dd></div>{% endif %}
<div><dt>Deadline</dt><dd>{% if brief.desired_deadline %}{{ brief.desired_deadline|date:"M j, Y" }}{% else %}Not specified{% endif %}</dd></div>
<div><dt>Last updated</dt><dd>{{ brief.updated_at|date:"M j, Y, P" }}</dd></div>
</dl>
{% if brief.description %}
<h3 class="portal-subtitle">Description &amp; goals</h3>
<p class="portal-body-text">{{ brief.description|linebreaksbr }}</p>
{% endif %}
{% if brief.reference_links %}
<h3 class="portal-subtitle">Reference links</h3>
<p class="portal-body-text">{{ brief.reference_links|linebreaksbr }}</p>
{% endif %}
{% if brief.attachments.exists %}
<h3 class="portal-subtitle">Attachments</h3>
<ul class="portal-attachment-list">
{% for attachment in brief.attachments.all %}
<li>{{ attachment.original_filename }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% if brief.shows_quote_to_client %}
<div class="glass-card portal-card fade-in">
<h2 class="portal-section-title">Quote from Tecvico</h2>
<p class="portal-body-text">{{ brief.quote_text|linebreaksbr }}</p>
</div>
{% endif %}
{% if brief.has_website_notes %}
<div class="glass-card portal-card fade-in">
<h2 class="portal-section-title">Notes from Tecvico</h2>
<p class="portal-body-text">{{ brief.website_notes|linebreaksbr }}</p>
</div>
{% endif %}
</div>
</div>
</section>
{% endblock %}
View File
+150
View File
@@ -0,0 +1,150 @@
{% extends "base.html" %}
{% load static %}
{% block title %}{{ form_title }}{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/brief-wizard.css' %}" />
{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="brief-form-heading">
<div class="container">
<div class="page-hero-content">
<h1 class="page-hero-title" id="brief-form-heading">{{ form_title }}</h1>
<p class="page-hero-subtitle">Complete each step to submit your project brief.</p>
</div>
</div>
</section>
<section class="section">
<div class="container container--narrow">
<div class="glass-card portal-card fade-in">
<form method="post" enctype="multipart/form-data" novalidate class="brief-wizard" data-brief-wizard data-initial-step="{{ initial_step }}">
{% csrf_token %}
<div class="wizard-progress" aria-hidden="true">
<div class="wizard-progress-track">
<div class="wizard-progress-fill" data-wizard-progress-fill></div>
</div>
</div>
<ol class="wizard-stepper" role="list">
{% for step in wizard_steps %}
<li class="wizard-stepper-item{% if forloop.first %} is-active{% endif %}" data-wizard-step-indicator="{{ forloop.counter }}">
<span class="wizard-stepper-number">{{ forloop.counter }}</span>
<span class="wizard-stepper-label">{{ step.title }}</span>
</li>
{% endfor %}
</ol>
{% for step in wizard_steps %}
<section
class="wizard-panel{% if forloop.first %} is-active{% endif %}"
data-wizard-panel="{{ forloop.counter }}"
data-step-fields="{{ step.fields|join:',' }}"
aria-labelledby="wizard-step-title-{{ forloop.counter }}"
{% if not forloop.first %}hidden{% endif %}
>
<header class="wizard-panel-header">
<p class="wizard-panel-eyebrow">Step {{ forloop.counter }} of {{ wizard_steps|length }}</p>
<h2 class="wizard-panel-title" id="wizard-step-title-{{ forloop.counter }}">{{ step.title }}</h2>
<p class="wizard-panel-subtitle">{{ step.subtitle }}</p>
</header>
{% if step.id == "basics" %}
<div class="form-group">
<label for="id_title">Project title <span class="required-star">*</span></label>
{{ form.title }}
{{ form.title.errors }}
</div>
<div class="form-group">
<label for="id_category">Category</label>
{{ form.category }}
{{ form.category.errors }}
</div>
{% endif %}
{% if step.id == "scope" %}
<div class="form-group">
<label for="id_description">Description &amp; goals</label>
{{ form.description }}
<p class="form-hint">Describe the project scope, context, and the outcomes you expect.</p>
{{ form.description.errors }}
</div>
{% endif %}
{% if step.id == "timeline" %}
<div class="form-grid form-grid--2">
<div class="form-group">
<label for="id_budget_range">Budget range</label>
{{ form.budget_range }}
{{ form.budget_range.errors }}
</div>
<div class="form-group">
<label for="id_desired_deadline">Desired deadline</label>
{{ form.desired_deadline }}
{{ form.desired_deadline.errors }}
</div>
</div>
{% endif %}
{% if step.id == "references" %}
<div class="form-group">
<label for="id_reference_links">Reference links</label>
{{ form.reference_links }}
<p class="form-hint">One URL per line — docs, mockups, repos, etc.</p>
{{ form.reference_links.errors }}
</div>
<div class="form-group">
<label for="id_attachments">Attachments</label>
<input type="file" name="attachments" id="id_attachments" multiple
accept=".png,.jpg,.jpeg,.gif,.webp,.bmp,.zip,.log,.txt"
class="file-input"
{% if brief and brief.attachments_locked %}disabled{% endif %} />
<p class="form-hint">Images, ZIP, or log/text files — up to 3 files, 10 MB each.</p>
{{ form.attachments.errors }}
</div>
{% if brief and brief.attachments.exists %}
<div class="portal-attachment-list">
<p class="form-hint">Existing attachments:</p>
<ul>
{% for attachment in brief.attachments.all %}
<li>{{ attachment.original_filename }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<div class="wizard-review" data-wizard-review hidden>
<h3 class="wizard-review-title">Review your brief</h3>
<dl class="wizard-review-list">
<div><dt>Title</dt><dd data-review-field="title"></dd></div>
<div><dt>Category</dt><dd data-review-field="category"></dd></div>
<div><dt>Description &amp; goals</dt><dd data-review-field="description"></dd></div>
<div><dt>Budget</dt><dd data-review-field="budget_range"></dd></div>
<div><dt>Deadline</dt><dd data-review-field="desired_deadline"></dd></div>
<div><dt>Reference links</dt><dd data-review-field="reference_links"></dd></div>
<div><dt>New attachments</dt><dd data-review-field="attachments">None</dd></div>
</dl>
</div>
{% endif %}
</section>
{% endfor %}
<div class="wizard-actions">
<button type="button" class="btn-ghost" data-wizard-prev hidden>Back</button>
<button type="button" class="btn-primary" data-wizard-next>Continue</button>
<button type="submit" class="btn-primary btn-submit" data-wizard-submit hidden>{{ submit_label }}</button>
</div>
</form>
</div>
</div>
</section>
{% endblock %}
{% block extra_js %}
<script src="{% static 'js/brief-wizard.js' %}"></script>
{% endblock %}
+70
View File
@@ -0,0 +1,70 @@
{% extends "base.html" %}
{% block title %}My Projects{% endblock %}
{% block content %}
<section class="page-hero" aria-labelledby="dashboard-heading">
<div class="container">
<div class="page-hero-content page-hero-content--row">
<div>
<div class="section-badge">Client Portal</div>
<h1 class="page-hero-title" id="dashboard-heading">My Projects</h1>
<p class="page-hero-subtitle">Track briefs you've submitted to the Tecvico team.</p>
</div>
<a href="{% url 'projects:create' %}" class="btn-primary">New project brief</a>
</div>
</div>
</section>
<section class="section">
<div class="container">
{% if briefs %}
<div class="portal-table-wrap glass-card fade-in">
<table class="portal-table">
<thead>
<tr>
<th>Title</th>
<th>Category</th>
<th>Status</th>
<th>Budget</th>
<th>Submitted</th>
<th></th>
</tr>
</thead>
<tbody>
{% for brief in briefs %}
<tr>
<td>{{ brief.title }}</td>
<td>{% if brief.category %}{{ brief.get_category_display }}{% else %}—{% endif %}</td>
<td><span class="status-pill status-pill--{{ brief.status }}">{{ brief.get_status_display }}</span></td>
<td>{% if brief.budget_range %}{{ brief.get_budget_range_display }}{% else %}—{% endif %}</td>
<td>{{ brief.submitted_at|date:"M j, Y" }}</td>
<td><a href="{% url 'projects:detail' pk=brief.pk %}" class="portal-link">View</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if page_obj.has_other_pages %}
<div class="portal-pagination">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}" class="portal-link">Previous</a>
{% endif %}
<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}" class="portal-link">Next</a>
{% endif %}
</div>
{% endif %}
{% else %}
<div class="glass-card portal-card portal-empty fade-in">
<h2>No project briefs yet</h2>
<p class="portal-intro">Describe what you need and our team will review your request.</p>
<a href="{% url 'projects:create' %}" class="btn-primary">Submit your first brief</a>
</div>
{% endif %}
</div>
</section>
{% endblock %}
@@ -0,0 +1,13 @@
New project brief submitted
Title: {{ brief.title }}
Client: {{ brief.client.get_full_name|default:brief.client.username }} ({{ brief.client.email }})
Category: {{ brief.get_category_display }}
Budget: {{ brief.get_budget_range_display }}
Status: {{ brief.get_status_display }}
Submitted: {{ brief.submitted_at }}
Description & goals:
{{ brief.description }}
Review in admin: /admin/projects/projectbrief/{{ brief.pk }}/change/
@@ -0,0 +1,13 @@
Hello {{ brief.client.first_name|default:brief.client.username }},
Your project "{{ brief.title }}" status changed from {{ previous_status }} to {{ brief.status }}.
{% if brief.shows_quote_to_client %}
Quote from Tecvico:
{{ brief.quote_text }}
{% endif %}
View your project: {{ brief.get_absolute_url }}
Thank you,
Tecvico Team