feat: restyle identify_confirm — match cards with confidence badges, location chips
This commit is contained in:
parent
2c45a6f2ee
commit
4e7655bf46
2 changed files with 96 additions and 45 deletions
|
|
@ -1,62 +1,109 @@
|
|||
{# plants/templates/plants/identify_confirm.html #}
|
||||
{% extends "plants/base.html" %}
|
||||
{% block title %}Confirm species — BloomBase{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<a href="{% url 'identify_upload' %}" class="btn btn-sm btn-outline-secondary">←</a>
|
||||
<h5 class="mb-0">Is this your plant?</h5>
|
||||
</div>
|
||||
<div class="px-4 pt-6">
|
||||
|
||||
<p class="text-muted small mb-3">Tap the correct species, then confirm.</p>
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<a href="{% url 'identify_upload' %}" class="btn-pill no-underline text-sm">←</a>
|
||||
<h1 class="font-nunito font-black text-[20px] text-[#1A1208]">Is this your plant?</h1>
|
||||
</div>
|
||||
<p class="font-nunito font-semibold text-[11px] text-[#B0A090] mb-4">
|
||||
Tap the correct species, then confirm.
|
||||
</p>
|
||||
|
||||
<form method="post" id="confirm-form">
|
||||
<form method="post" id="confirm-form">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="match_idx" id="match_idx_input" value="0">
|
||||
|
||||
<div class="d-flex flex-column gap-2 mb-4" id="match-list">
|
||||
<div class="flex flex-col gap-3 mb-5" id="match-list">
|
||||
{% for m in matches %}
|
||||
<div class="match-card d-flex align-items-center gap-3 p-3 border rounded"
|
||||
style="cursor:pointer; {% if forloop.first %}border-color:#52b788 !important; background:#f0faf4;{% endif %}"
|
||||
<div class="match-card flex items-center gap-3 bg-white rounded-2xl p-3 shadow-sm cursor-pointer
|
||||
{% if forloop.first %}ring-2 ring-[#F07040]{% endif %}"
|
||||
data-idx="{{ forloop.counter0 }}"
|
||||
data-name="{{ m.scientific_name }}"
|
||||
onclick="selectMatch(this)">
|
||||
{% if m.image_url %}
|
||||
<img src="{{ m.image_url }}" alt="{{ m.scientific_name }}"
|
||||
style="width:64px;height:64px;object-fit:cover;border-radius:8px;flex-shrink:0;">
|
||||
class="w-16 h-16 rounded-xl flex-shrink-0 object-cover">
|
||||
{% else %}
|
||||
<div style="width:64px;height:64px;background:#e9ecef;border-radius:8px;flex-shrink:0;"></div>
|
||||
<div class="w-16 h-16 bg-[#D8F3DC] rounded-xl flex-shrink-0 flex items-center justify-center text-2xl">🌿</div>
|
||||
{% endif %}
|
||||
<div class="flex-grow-1">
|
||||
<div class="fw-bold">{{ m.scientific_name }}</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-nunito font-extrabold text-[13px] text-[#1A1208]">{{ m.scientific_name }}</div>
|
||||
{% if m.common_names %}
|
||||
<div class="text-muted small">{{ m.common_names|join:", " }}</div>
|
||||
{% endif %}
|
||||
<div class="text-muted small fst-italic">{{ m.family }}</div>
|
||||
<div class="font-nunito text-[10px] font-semibold text-[#B0A090] mt-0.5 truncate">
|
||||
{{ m.common_names|join:", " }}
|
||||
</div>
|
||||
<div>
|
||||
<span class="badge {% if m.score >= 0.70 %}bg-success{% elif m.score >= 0.30 %}bg-warning text-dark{% else %}bg-secondary{% endif %}">
|
||||
{% endif %}
|
||||
<div class="font-nunito text-[10px] font-semibold text-[#B0A090] italic">{{ m.family }}</div>
|
||||
</div>
|
||||
<span class="font-nunito font-bold text-[11px] px-2 py-1 rounded-full flex-shrink-0
|
||||
{% if m.score >= 0.70 %}bg-green-100 text-green-700
|
||||
{% elif m.score >= 0.30 %}bg-orange-100 text-orange-700
|
||||
{% else %}bg-gray-100 text-gray-500{% endif %}">
|
||||
{% widthratio m.score 1 100 %}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success w-100" id="confirm-btn">
|
||||
Use <span id="selected-name">{{ matches.0.scientific_name }}</span> →
|
||||
<!-- Plant name override -->
|
||||
<div class="mb-4">
|
||||
<label class="font-nunito font-bold text-[11px] text-[#B0A090] block mb-1">Plant name (optional)</label>
|
||||
<input type="text" name="plant_name" id="plant-name-input"
|
||||
class="w-full bg-white border border-[#F0E4D4] rounded-full px-4 py-2.5
|
||||
font-nunito text-sm text-[#1A1208] placeholder-[#C0B0A0]
|
||||
outline-none focus:border-[#F07040]"
|
||||
placeholder="Leave blank to use species name">
|
||||
</div>
|
||||
|
||||
<!-- Location picker -->
|
||||
{% if locations %}
|
||||
<div class="mb-5">
|
||||
<label class="font-nunito font-bold text-[11px] text-[#B0A090] block mb-2">Add to area</label>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<input type="hidden" name="location_id" id="location-id-input" value="">
|
||||
{% for loc in locations %}
|
||||
<span class="location-chip font-nunito font-bold text-[11px] px-3 py-1.5 rounded-full
|
||||
bg-[#F5F0EA] text-[#B0A090] cursor-pointer"
|
||||
data-id="{{ loc.pk }}"
|
||||
onclick="selectLocation(this)">
|
||||
{{ loc.name }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<button type="submit" class="btn-bloom">
|
||||
Add to my garden →
|
||||
</button>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function selectMatch(el) {
|
||||
document.querySelectorAll('.match-card').forEach(c => {
|
||||
c.style.borderColor = '';
|
||||
c.style.background = '';
|
||||
function selectMatch(card) {
|
||||
document.querySelectorAll('.match-card').forEach(c => c.classList.remove('ring-2', 'ring-[#F07040]'));
|
||||
card.classList.add('ring-2', 'ring-[#F07040]');
|
||||
document.getElementById('match_idx_input').value = card.dataset.idx;
|
||||
const nameInput = document.getElementById('plant-name-input');
|
||||
if (!nameInput.value || nameInput.dataset.autoSet) {
|
||||
nameInput.value = card.dataset.name;
|
||||
nameInput.dataset.autoSet = '1';
|
||||
}
|
||||
}
|
||||
|
||||
function selectLocation(chip) {
|
||||
document.querySelectorAll('.location-chip').forEach(c => {
|
||||
c.classList.remove('bg-[#F07040]', 'text-white');
|
||||
c.classList.add('bg-[#F5F0EA]', 'text-[#B0A090]');
|
||||
});
|
||||
el.style.borderColor = '#52b788';
|
||||
el.style.background = '#f0faf4';
|
||||
document.getElementById('match_idx_input').value = el.dataset.idx;
|
||||
document.getElementById('selected-name').textContent = el.dataset.name;
|
||||
chip.classList.remove('bg-[#F5F0EA]', 'text-[#B0A090]');
|
||||
chip.classList.add('bg-[#F07040]', 'text-white');
|
||||
document.getElementById('location-id-input').value = chip.dataset.id;
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,11 @@ def identify_confirm(request):
|
|||
|
||||
return redirect('identify_fields')
|
||||
|
||||
return render(request, 'plants/identify_confirm.html', {'matches': matches})
|
||||
locations = list(Location.objects.all())
|
||||
return render(request, 'plants/identify_confirm.html', {
|
||||
'matches': matches,
|
||||
'locations': locations,
|
||||
})
|
||||
|
||||
|
||||
def _apply_vpc_care_fields(species, vpc_result):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue