feat: restyle dashboard as camera-first Home screen

This commit is contained in:
Stephan Kerkman 2026-06-01 16:49:13 +02:00
parent b320b1a471
commit d7cb9ea25d
2 changed files with 90 additions and 62 deletions

View file

@ -1,71 +1,95 @@
{# plants/templates/plants/dashboard.html #}
{% extends "plants/base.html" %} {% extends "plants/base.html" %}
{% load plant_extras %} {% load plant_extras %}
{% block title %}Dashboard — BloomBase{% endblock %} {% block title %}BloomBase{% endblock %}
{% block content %} {% block content %}
<h6 class="text-muted mb-3">{{ today|date:"F Y" }}</h6>
<div class="row g-2 mb-3"> <!-- Top bar: hamburger + bell -->
<div class="col-6"> <div class="flex justify-between items-center px-4 pt-6 pb-2">
<a href="{% url 'plant_list' %}" class="text-decoration-none"> <button class="p-1" aria-label="Menu">
<div class="card text-center h-100" style="background:#d8f3dc;"> <svg width="22" height="22" fill="none" stroke="#1A1208" stroke-width="2" viewBox="0 0 24 24">
<div class="card-body py-3"> <path d="M3 12h18M3 6h18M3 18h18"/>
<div class="display-5 fw-bold" style="color:#1b4332;">{{ total_plants }}</div> </svg>
<div class="small" style="color:#2d6a4f;">Plants</div> </button>
<button class="p-1" aria-label="Notifications">
<svg width="22" height="22" fill="none" stroke="#1A1208" stroke-width="2" viewBox="0 0 24 24">
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
</svg>
</button>
</div> </div>
<div class="px-4">
<!-- Greeting + headline -->
<p class="font-nunito font-semibold text-[11px] text-[#B0A090] mb-0.5">Hello, Plant Lover! 🌿</p>
<h1 class="font-nunito font-black text-[24px] text-[#1A1208] leading-tight mb-1">
What are we <span class="text-[#F07040]">growing</span> today?
</h1>
<p class="font-nunito font-semibold text-[11px] text-[#B0A090] mb-4">
Identify a plant and add it to Bloombase.
</p>
<!-- Camera viewfinder — tap → identify_upload -->
<a href="{% url 'identify_upload' %}" class="block relative bg-[#2C3820] rounded-2xl h-[120px] overflow-hidden mb-4 no-underline">
<!-- Simulated plant in viewfinder -->
<div class="absolute inset-0"
style="background: radial-gradient(ellipse 60% 55% at 60% 45%, #C84060 0%, #E05878 30%, #F880A0 55%, transparent 75%),
radial-gradient(ellipse 40% 35% at 40% 55%, #C04050 0%, #D86070 40%, transparent 70%),
linear-gradient(160deg, #1E3018 0%, #2E5028 30%, #3A6832 50%, #2C5020 70%);"></div>
<!-- Corner brackets -->
<div class="vf-corner vf-tl"></div>
<div class="vf-corner vf-tr"></div>
<div class="vf-corner vf-bl"></div>
<div class="vf-corner vf-br"></div>
<!-- Shutter + gallery -->
<div class="absolute bottom-3 left-0 right-0 flex justify-center items-center gap-6">
<div class="w-8 h-8 bg-white/20 rounded-xl flex items-center justify-center border border-white/40">
<svg width="14" height="14" fill="none" stroke="white" stroke-width="2" viewBox="0 0 24 24">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="12" cy="12" r="4"/>
</svg>
</div>
<div class="w-10 h-10 rounded-full bb-fab"></div>
</div> </div>
</a> </a>
</div>
<div class="col-6">
<div class="card text-center h-100" style="background:#d8f3dc;">
<div class="card-body py-3">
<div class="display-5 fw-bold" style="color:#1b4332;">{{ blooming_now_count }}</div>
<div class="small" style="color:#2d6a4f;">Blooming now</div>
</div>
</div>
</div>
</div>
{% if blooming_now %} <!-- My Garden pill -->
<div class="card mb-3"> <a href="{% url 'location_list' %}"
<div class="card-header fw-semibold">🌸 Blooming this month</div> class="flex items-center gap-3 bg-white/80 rounded-2xl px-4 py-3 border border-[#F0E4D4] mb-5 no-underline">
<div class="list-group list-group-flush"> <span class="text-2xl">🪴</span>
{% for plant in blooming_now %} <div class="flex-1">
<a href="{% url 'plant_detail' plant.pk %}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"> <div class="font-nunito font-extrabold text-[13px] text-[#1A1208]">My Garden</div>
<div> <div class="font-nunito text-[10px] font-semibold text-[#B0A090]">
<div class="fw-semibold">{{ plant.name }}</div> {{ total_plants }} Plant{{ total_plants|pluralize }} · {{ location_count }} Area{{ location_count|pluralize }}
<small class="text-muted">{{ plant.location }}</small>
</div> </div>
<div>{% month_strip plant.bloom_months %}</div> </div>
<span class="text-[#D0C0B0] font-bold text-lg"></span>
</a> </a>
{% endfor %}
</div>
</div>
{% endif %}
<!-- Recently added -->
{% if latest_plants %} {% if latest_plants %}
<div class="card mb-3"> <h2 class="font-nunito font-black text-[16px] text-[#1A1208] mb-3">🌿 Recently added</h2>
<div class="card-header fw-semibold">🌿 Recently added</div> <div class="flex flex-col gap-2 mb-4">
<div class="list-group list-group-flush">
{% for plant in latest_plants %} {% for plant in latest_plants %}
<a href="{% url 'plant_detail' plant.pk %}" class="list-group-item list-group-item-action d-flex align-items-center gap-3 py-2 text-decoration-none"> <a href="{% url 'plant_detail' plant.pk %}"
class="flex items-center gap-3 bg-white rounded-2xl px-3 py-2.5 shadow-sm no-underline">
{% if plant.species and plant.species.api_image_url %} {% if plant.species and plant.species.api_image_url %}
<img src="{{ plant.species.api_image_url }}" width="48" height="48" class="rounded" style="object-fit:cover;flex-shrink:0;"> <img src="{{ plant.species.api_image_url }}" width="44" height="44"
class="rounded-xl flex-shrink-0" style="object-fit:cover;">
{% elif plant.thumbnail_url %} {% elif plant.thumbnail_url %}
<img src="{{ plant.thumbnail_url }}" width="48" height="48" class="rounded" style="object-fit:cover;flex-shrink:0;"> <img src="{{ plant.thumbnail_url }}" width="44" height="44"
class="rounded-xl flex-shrink-0" style="object-fit:cover;">
{% else %} {% else %}
<div style="width:48px;height:48px;background:#d8f3dc;border-radius:.375rem;flex-shrink:0;display:flex;align-items:center;justify-content:center;">🌿</div> <div class="w-11 h-11 bg-[#D8F3DC] rounded-xl flex-shrink-0 flex items-center justify-center text-xl">🌿</div>
{% endif %} {% endif %}
<div> <div>
<div class="fw-semibold" style="color:#1b4332;">{{ plant.name }}</div> <div class="font-nunito font-extrabold text-[13px] text-[#1A1208]">{{ plant.name }}</div>
<small class="text-muted">{{ plant.location }}</small> <div class="font-nunito text-[10px] font-semibold text-[#B0A090]">{{ plant.location }}</div>
</div> </div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
</div>
{% endif %} {% endif %}
<div class="d-grid">
<a href="{% url 'plant_add' %}" class="btn btn-success">+ Add a plant</a>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,6 +1,7 @@
# plants/views/dashboard.py
from datetime import date from datetime import date
from django.shortcuts import render from django.shortcuts import render
from plants.models import Plant from plants.models import Plant, Location
def dashboard(request): def dashboard(request):
@ -8,6 +9,7 @@ def dashboard(request):
all_plants = list(Plant.objects.select_related('species').all()) all_plants = list(Plant.objects.select_related('species').all())
blooming_now = [p for p in all_plants if today.month in (p.bloom_months or [])] blooming_now = [p for p in all_plants if today.month in (p.bloom_months or [])]
latest_plants = Plant.objects.select_related('species', 'location').prefetch_related('photos').order_by('-pk')[:6] latest_plants = Plant.objects.select_related('species', 'location').prefetch_related('photos').order_by('-pk')[:6]
location_count = Location.objects.count()
return render(request, 'plants/dashboard.html', { return render(request, 'plants/dashboard.html', {
'total_plants': len(all_plants), 'total_plants': len(all_plants),
@ -15,4 +17,6 @@ def dashboard(request):
'blooming_now_count': len(blooming_now), 'blooming_now_count': len(blooming_now),
'today': today, 'today': today,
'latest_plants': latest_plants, 'latest_plants': latest_plants,
'location_count': location_count,
'active_tab': 'home',
}) })