Files
links/templates/pricemon/watcher_form.html
T
2026-05-11 21:53:43 +10:00

158 lines
6.6 KiB
HTML

{% extends "base.html" %}
{% load i18n %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="max-w-5xl mx-auto px-4 py-6">
<div class="flex items-center gap-3 mb-6">
<a href="{% url 'pricemon-dashboard' %}"
class="text-gray-400 hover:text-gray-600 transition">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
</svg>
</a>
<h1 class="text-xl font-bold text-gray-900">{{ title }}</h1>
</div>
{% if messages %}
{% for msg in messages %}
<div class="mb-4 px-4 py-3 rounded-lg text-sm
{% if msg.tags == 'error' %}bg-red-50 text-red-700 border border-red-100
{% else %}bg-green-50 text-green-700 border border-green-100{% endif %}">
{{ msg }}
</div>
{% endfor %}
{% endif %}
<div class="bg-white rounded-lg shadow-sm border border-gray-100 p-8">
<form method="post" id="watcher-form" class="space-y-6">
{% csrf_token %}
{% if form.non_field_errors %}
<div class="px-4 py-3 rounded-lg bg-red-50 border border-red-100 text-sm text-red-700">
{{ form.non_field_errors }}
</div>
{% endif %}
<!-- Name (full width) -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
{{ form.name.label }} <span class="text-red-500">*</span>
</label>
{{ form.name }}
{% for e in form.name.errors %}<p class="text-xs text-red-600 mt-1">{{ e }}</p>{% endfor %}
</div>
<!-- URL (full width) -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
{{ form.url.label }} <span class="text-red-500">*</span>
</label>
{{ form.url }}
{% for e in form.url.errors %}<p class="text-xs text-red-600 mt-1">{{ e }}</p>{% endfor %}
</div>
<!-- CSS Selector + Test button (full width) -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
{{ form.css_selector.label }} <span class="text-red-500">*</span>
</label>
<div class="flex gap-2 items-start">
<div class="flex-1">{{ form.css_selector }}</div>
<button type="button"
id="test-selector-btn"
class="flex-shrink-0 mt-px inline-flex items-center gap-1.5 px-3 py-2 text-sm font-medium text-indigo-700 bg-indigo-50 border border-indigo-200 rounded-md hover:bg-indigo-100 transition"
hx-post="{% url 'pricemon-test-selector' %}"
hx-include="#watcher-form [name='url'], #watcher-form [name='css_selector']"
hx-target="#selector-test-result"
hx-swap="innerHTML">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span id="test-btn-label">{% trans "Test" %}</span>
</button>
</div>
<div id="selector-test-result" class="mt-2"></div>
<p class="text-xs text-gray-400 mt-1">{{ form.css_selector.help_text }}</p>
{% for e in form.css_selector.errors %}<p class="text-xs text-red-600 mt-1">{{ e }}</p>{% endfor %}
</div>
<!-- Row: Check interval + Alert price threshold -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
{{ form.check_interval_hours.label }} <span class="text-red-500">*</span>
</label>
{{ form.check_interval_hours }}
{% for e in form.check_interval_hours.errors %}<p class="text-xs text-red-600 mt-1">{{ e }}</p>{% endfor %}
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
{{ form.alert_price_threshold.label }}
</label>
{{ form.alert_price_threshold }}
<p class="text-xs text-gray-400 mt-1">{{ form.alert_price_threshold.help_text }}</p>
{% for e in form.alert_price_threshold.errors %}<p class="text-xs text-red-600 mt-1">{{ e }}</p>{% endfor %}
</div>
</div>
<!-- Row: Recurring notification + Enabled -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div class="flex items-start gap-3">
{{ form.recurring_notification }}
<div>
<label class="block text-sm font-medium text-gray-700">{{ form.recurring_notification.label }}</label>
<p class="text-xs text-gray-400 mt-0.5">{{ form.recurring_notification.help_text }}</p>
</div>
{% for e in form.recurring_notification.errors %}<p class="text-xs text-red-600 mt-1">{{ e }}</p>{% endfor %}
</div>
<div class="flex items-start gap-3">
{{ form.enabled }}
<div>
<label class="block text-sm font-medium text-gray-700">{{ form.enabled.label }}</label>
<p class="text-xs text-gray-400 mt-0.5">{% trans "Uncheck to pause price checks for this watcher." %}</p>
</div>
{% for e in form.enabled.errors %}<p class="text-xs text-red-600 mt-1">{{ e }}</p>{% endfor %}
</div>
</div>
<div class="flex items-center gap-3 pt-2 border-t border-gray-100">
<button type="submit"
class="px-6 py-2 bg-indigo-600 text-white text-sm font-medium rounded-lg hover:bg-indigo-700 transition">
{% trans "Save" %}
</button>
<a href="{% url 'pricemon-dashboard' %}"
class="px-6 py-2 bg-gray-100 text-gray-700 text-sm font-medium rounded-lg hover:bg-gray-200 transition">
{% trans "Cancel" %}
</a>
</div>
</form>
</div>
<div class="mt-4 text-xs text-gray-400">
<p>{% trans "Selector tip:" %} inspect the price on the product page and find its CSS class. E.g. <code class="bg-gray-100 px-1 rounded">.product-price</code> or <code class="bg-gray-100 px-1 rounded">span[itemprop="price"]</code></p>
</div>
</div>
{% block extra_js %}
<script>
document.addEventListener('htmx:beforeRequest', function(e) {
if (e.target.id === 'test-selector-btn') {
document.getElementById('test-btn-label').textContent = '{% trans "Testing…" %}';
e.target.disabled = true;
}
});
document.addEventListener('htmx:afterRequest', function(e) {
if (e.target.id === 'test-selector-btn') {
document.getElementById('test-btn-label').textContent = '{% trans "Test" %}';
e.target.disabled = false;
}
});
</script>
{% endblock %}
{% endblock %}