Stand up Print Forge as a 3D-printed toy shop with color variants and printer photography.

Replaces the client_site template branding, adds shop/shipping, and points beta CI at master for easy deploy.

Closes #1
This commit is contained in:
2026-09-06 08:28:04 -05:00
parent 8a97e3fbe2
commit b2029b6c0f
336 changed files with 9241 additions and 2537 deletions
+17
View File
@@ -0,0 +1,17 @@
{% extends "base.html" %}
{% block title %}Tickets · {{ event.title }}{% endblock %}
{% block content %}
<section class="section section-lg">
<div class="container">
<h1>Tickets · {{ event.title }}</h1>
<p>{{ event.price }} {{ event.currency|upper }} each{% if event.seats_remaining is not None %} · {{ event.seats_remaining }} left{% endif %}</p>
<form method="post">
{% csrf_token %}
<p><label>Email <input name="email" type="email" required></label></p>
<p><label>Name <input name="customer_name"></label></p>
<p><label>Quantity <input name="quantity" type="number" min="1" value="1"></label></p>
<button class="button button-primary" type="submit">Pay with Stripe</button>
</form>
</div>
</section>
{% endblock %}
+8
View File
@@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block title %}Checkout cancelled{% endblock %}
{% block content %}
<section class="section section-lg"><div class="container">
<h1>Checkout cancelled</h1>
<p>No charge for {{ order.event.title }}. <a href="{% url 'events:buy' order.event.slug %}">Try again</a>.</p>
</div></section>
{% endblock %}
+18
View File
@@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block title %}{{ event.title }} · {{ SITE_NAME }}{% endblock %}
{% block content %}
<section class="section section-lg">
<div class="container">
<p><a href="{% url 'events:list' %}">← Events</a></p>
<h1>{{ event.title }}</h1>
<p class="muted">{{ event.starts_at|date:"F j, Y g:i A" }}{% if event.venue %} · {{ event.venue }}{% endif %}</p>
<div>{{ event.description|linebreaks }}</div>
<p>{{ event.price }} {{ event.currency|upper }}</p>
{% if event.seats_remaining == 0 %}
<p>Sold out.</p>
{% else %}
<p><a class="button button-primary" href="{% url 'events:buy' event.slug %}">Buy tickets</a></p>
{% endif %}
</div>
</section>
{% endblock %}
+18
View File
@@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block title %}Events · {{ SITE_NAME }}{% endblock %}
{% block content %}
<section class="section section-lg">
<div class="container">
<h1 class="text-uppercase">Events</h1>
{% for event in events %}
<article style="margin:0 0 32px">
<h2><a href="{{ event.get_absolute_url }}">{{ event.title }}</a></h2>
<p class="muted">{{ event.starts_at|date:"F j, Y g:i A" }}{% if event.venue %} · {{ event.venue }}{% endif %}</p>
<p>{{ event.price }} {{ event.currency|upper }}{% if event.seats_remaining is not None %} · {{ event.seats_remaining }} seats left{% endif %}</p>
</article>
{% empty %}
<p>No upcoming events.</p>
{% endfor %}
</div>
</section>
{% endblock %}
@@ -0,0 +1,23 @@
{% extends "portal_base.html" %}
{% block title %}{{ event.title }} · Portal{% endblock %}
{% block topbar_title %}{{ event.title }}{% endblock %}
{% block portal_content %}
<p><a class="btn btn-ghost" href="{% url 'events_portal:event_edit' event.pk %}">Edit</a></p>
<p>{{ event.starts_at }} · {{ event.tickets_sold }} / {{ event.capacity|default:"∞" }} seats · {{ event.price }} {{ event.currency|upper }}</p>
<table class="table">
<thead><tr><th>Order</th><th>Email</th><th>Qty</th><th>Status</th><th>Codes</th></tr></thead>
<tbody>
{% for order in orders %}
<tr>
<td>{{ order.number }}</td>
<td>{{ order.email }}</td>
<td>{{ order.quantity }}</td>
<td>{{ order.get_status_display }}</td>
<td>{% for ticket in order.tickets.all %}{{ ticket.code }}{% if not forloop.last %}, {% endif %}{% endfor %}</td>
</tr>
{% empty %}
<tr><td colspan="5" class="empty-state">No ticket orders yet.</td></tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
@@ -0,0 +1,17 @@
{% extends "portal_base.html" %}
{% block title %}{% if event %}Edit{% else %}New{% endif %} event · Portal{% endblock %}
{% block topbar_title %}{% if event %}Edit event{% else %}New event{% endif %}{% endblock %}
{% block portal_content %}
<form method="post" class="form-grid">
{% csrf_token %}
<div class="field"><label>Title</label><input name="title" required value="{{ event.title|default:'' }}"></div>
<div class="field"><label>Slug</label><input name="slug" value="{{ event.slug|default:'' }}" placeholder="auto from title"></div>
<div class="field"><label>Starts</label><input name="starts_at" type="datetime-local" required value="{% if event %}{{ event.starts_at|date:'Y-m-d\\TH:i' }}{% endif %}"></div>
<div class="field"><label>Venue</label><input name="venue" value="{{ event.venue|default:'' }}"></div>
<div class="field"><label>Capacity</label><input name="capacity" type="number" min="0" value="{{ event.capacity|default:0 }}"></div>
<div class="field"><label>Price</label><input name="price" type="number" step="0.01" min="0" required value="{{ event.price|default:'0' }}"></div>
<div class="field"><label>Description</label><textarea name="description" style="min-height:120px">{{ event.description|default:'' }}</textarea></div>
<label><input type="checkbox" name="is_published" {% if event.is_published %}checked{% endif %}> Published</label>
<button class="btn btn-primary" type="submit">Save</button>
</form>
{% endblock %}
@@ -0,0 +1,21 @@
{% extends "portal_base.html" %}
{% block title %}Events · Portal{% endblock %}
{% block topbar_title %}Events{% endblock %}
{% block portal_content %}
<p><a class="btn btn-primary" href="{% url 'events_portal:event_new' %}">New event</a></p>
<table class="table">
<thead><tr><th>Title</th><th>When</th><th>Capacity</th><th>Status</th></tr></thead>
<tbody>
{% for event in events %}
<tr>
<td><a href="{% url 'events_portal:event_detail' event.pk %}">{{ event.title }}</a></td>
<td>{{ event.starts_at }}</td>
<td>{{ event.tickets_sold }} / {{ event.capacity|default:"∞" }}</td>
<td>{% if event.is_published %}Published{% else %}Draft{% endif %}</td>
</tr>
{% empty %}
<tr><td colspan="4" class="empty-state">No events yet.</td></tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
@@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block title %}Tickets {{ order.number }}{% endblock %}
{% block content %}
<section class="section section-lg"><div class="container">
<h1>You're in</h1>
<p>Order {{ order.number }} for {{ order.event.title }} is {{ order.get_status_display|lower }}.</p>
<p>Ticket codes will be emailed to {{ order.email }}.</p>
</div></section>
{% endblock %}