generated from westfarn/web_django_template
Ship Print Forge shop site (colors, photos, 3D viewer) (#2)
## Summary - Rebrand the Django client template as Print Forge (`client_site` → `print_forge`) with shop + shipping enabled. - Product listings support multiple photos, color variants (shared price/description/STL, per-color stock and photos), and a photo-first / 3D-second gallery. - Public pages use 3D printer / printed-toy photography instead of leftover t-shirt mockups; beta CI deploys on `master`. Closes #1 Infra: [server-infra#27](ai_ml_operations/server-infra#27) (easy deploy beta). ## Test plan - [ ] Product page shows photo first, 3D model second; color swatches swap photos and stock - [ ] Portal can upload multiple photos and per-color qty/images; STL stays shared - [ ] Public home/about/gallery have no t-shirt mockups - [ ] `manage.py test` passes - [ ] After server-infra#27: beta deploy to `print-forge-preview.aimloperations.com` Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
{% extends "portal_base.html" %}
|
||||
{% block title %}{{ shipment.order.number }} · Shipping{% endblock %}
|
||||
{% block topbar_title %}{{ shipment.order.number }}{% endblock %}
|
||||
{% block portal_content %}
|
||||
<p>{{ shipment.order.email }} · {{ shipment.get_status_display }}</p>
|
||||
{% if shipment.tracking_number %}<p>Tracking: {{ shipment.tracking_number }}</p>{% endif %}
|
||||
{% if shipment.label_url %}<p><a href="{{ shipment.label_url }}">Download label</a></p>{% endif %}
|
||||
{% if shipment.status != 'labeled' %}
|
||||
<form method="post" action="{% url 'shipping:shipment_buy' shipment.pk %}">
|
||||
{% csrf_token %}
|
||||
{% for rate in shipment.rates %}
|
||||
<label>
|
||||
<input type="radio" name="rate_id" value="{{ rate.id }}" {% if forloop.first %}checked{% endif %}>
|
||||
{{ rate.carrier }} {{ rate.service }} — {{ rate.rate }} {{ rate.currency }}
|
||||
</label><br>
|
||||
{% empty %}
|
||||
<p>No rates yet.</p>
|
||||
{% endfor %}
|
||||
{% if shipment.rates %}
|
||||
<button class="btn btn-primary" type="submit">Buy label</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endif %}
|
||||
<p><a href="{% url 'shipping:shipment_list' %}">← All shipments</a></p>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,43 @@
|
||||
{% extends "portal_base.html" %}
|
||||
{% block title %}Shipping · Portal{% endblock %}
|
||||
{% block topbar_title %}Shipping{% endblock %}
|
||||
{% block portal_content %}
|
||||
<p><a class="btn btn-ghost" href="{% url 'shipping:pirate_ship_export' %}">Pirate Ship CSV</a></p>
|
||||
<h2>Unshipped paid orders</h2>
|
||||
<table class="table">
|
||||
<thead><tr><th>Order</th><th>Email</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for order in unshipped %}
|
||||
<tr>
|
||||
<td>{{ order.number }}</td>
|
||||
<td>{{ order.email }}</td>
|
||||
<td>
|
||||
<form method="post" action="{% url 'shipping:shipment_create' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="order" value="{{ order.pk }}">
|
||||
<input name="weight_oz" type="number" min="1" value="16" style="width:5rem"> oz
|
||||
<button class="btn btn-primary" type="submit">Quote rates</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="3" class="empty-state">No paid orders waiting to ship.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Shipments</h2>
|
||||
<table class="table">
|
||||
<thead><tr><th>Order</th><th>Status</th><th>Tracking</th></tr></thead>
|
||||
<tbody>
|
||||
{% for shipment in shipments %}
|
||||
<tr>
|
||||
<td><a href="{% url 'shipping:shipment_detail' shipment.pk %}">{{ shipment.order.number }}</a></td>
|
||||
<td>{{ shipment.get_status_display }}</td>
|
||||
<td>{{ shipment.tracking_number|default:"—" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="3" class="empty-state">No shipments yet.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user