Initial commit

This commit is contained in:
ThePetrovich 2026-08-17 22:42:04 +08:00
commit 97e799fd52
61 changed files with 2252 additions and 0 deletions

View file

@ -0,0 +1,18 @@
{% load i18n %}
<div id="cookie-banner" class="cookie-banner d-none" role="dialog" aria-live="polite" aria-label="Cookie consent banner">
<div class="container py-3">
<div class="row g-2 align-items-center">
<div class="col-lg-8">
<div class="fw-bold mb-1">{% trans "Cookie Notice" %}</div>
<div class="small mb-0">
{% trans "This site uses essential cookies for language and time zone preferences. You can review details in our cookie policy." %}
<a href="{% url 'cookie-policy' %}">{% trans "Read cookie policy" %}</a>.
</div>
</div>
<div class="col-lg-4 text-lg-end d-flex gap-2 justify-content-lg-end">
<button type="button" class="btn btn-outline-light btn-sm" data-cookie-consent="rejected">{% trans "Reject" %}</button>
<button type="button" class="btn btn-light btn-sm" data-cookie-consent="accepted">{% trans "Accept" %}</button>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,18 @@
{% load static i18n %}{% comment %}
Layout-identical across every YKSA service. Do not restyle here; change it in
all of them or, better, in yksa-web-kit once that exists.
{% endcomment %}
<footer class="bg-dark text-bg-dark mt-auto">
<div class="container pb-4 pt-4">
<div class="row">
<div class="col-6 small">
<div>{% blocktrans %}Copyright © 2026 Sakha Aerospace Systems, LLC{% endblocktrans %}</div>
</div>
<div class="col-6 text-end small">
<a class="text-decoration-none" href="{% url 'privacy-policy' %}">{% trans "Privacy Policy" %}</a>
&ndash;
<a class="text-decoration-none" href="{% url 'cookie-policy' %}">{% trans "Cookie Policy" %}</a>
</div>
</div>
</div>
</footer>

View file

@ -0,0 +1,26 @@
{% comment %}
Floating toast stack for Django messages. Rendered outside <main> so it never
disturbs page layout (the old top-of-main alert block used to shove the pass
page around). z-index sits above the pass action bar (1030).
{% endcomment %}
{% if messages %}
<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1100;">
{% for message in messages %}
{% if message.tags == 'error' %}{% with level='danger' %}
<div class="toast align-items-center text-bg-{{ level }} border-0" role="alert" aria-live="assertive" aria-atomic="true" data-bs-autohide="false">
<div class="d-flex">
<div class="toast-body">{{ message }}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
{% endwith %}{% else %}{% with level=message.tags|default:'info' %}
<div class="toast align-items-center text-bg-{{ level }} border-0" role="alert" aria-live="assertive" aria-atomic="true">
<div class="d-flex">
<div class="toast-body">{{ message }}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
{% endwith %}{% endif %}
{% endfor %}
</div>
{% endif %}

View file

@ -0,0 +1,42 @@
{% comment %}
Reusable chip-style filter group.
Drop this partial into any list/catalog page. Multiple groups can live in the
same enclosing <form>; each one drives its own comma-separated hidden input.
Required context:
* name: string -- the group key. The hidden input MUST be present in the
parent template as
<input type="hidden" name="{{ name }}" value="..."
data-filter-csv="{{ name }}">
(kept in the parent so callers control its initial value).
* label: string -- heading shown above the chips.
* chips: iterable of {value, label, selected} dicts.
Optional context:
* empty_message: text shown when ``chips`` is empty (defaults to a generic
placeholder via {{ empty_message|default:_("No options yet.") }}).
The accompanying JS (static/src/chip-filters.js) toggles ``.filter-chip.active``
on click and re-emits the comma-separated value into the hidden input keyed by
``data-filter-csv``. Submitting the form sends the result; servers split on
comma. No XHR -- keeps URLs bookmarkable.
{% endcomment %}
{% load i18n %}
<div class="card mb-3">
<div class="card-body">
{% if label %}<h2 class="h6 mb-2">{{ label }}</h2>{% endif %}
{% if chips %}
<div class="d-flex flex-wrap gap-1" data-filter-group="{{ name }}">
{% for chip in chips %}
<span class="badge bg-secondary filter-chip {% if chip.selected %}active{% endif %}"
data-value="{{ chip.value }}">{{ chip.label }}</span>
{% endfor %}
</div>
{% else %}
<p class="small text-body-secondary mb-0">
{{ empty_message|default:_("No options yet.") }}
</p>
{% endif %}
</div>
</div>