diff --git a/plants/templates/plants/identify_fields.html b/plants/templates/plants/identify_fields.html
index 8b083e8..33e5a8b 100644
--- a/plants/templates/plants/identify_fields.html
+++ b/plants/templates/plants/identify_fields.html
@@ -1,5 +1,133 @@
{% extends "plants/base.html" %}
-{% block title %}Review fields — PlantDB{% endblock %}
+{% block title %}Review & save — PlantDB{% endblock %}
{% block content %}
-
Fields step (coming soon)
+
+
+
+Tap a tile to switch source. Green border = selected.
+
+{% if vpc_match %}
+
+
🏪
+
+
{{ vpc_match.common_name }}
+
vasteplantencatalogus.nl
+
+ {% if vpc_results|length > 1 %}
+
+
+
+
+ {% endif %}
+
+{% else %}
+
+ No VPC data found — using Pl@ntNet data only.
+
+{% endif %}
+
+
+
+
{% endblock %}
diff --git a/plants/tests/test_identify_views.py b/plants/tests/test_identify_views.py
index 1792da2..1de8960 100644
--- a/plants/tests/test_identify_views.py
+++ b/plants/tests/test_identify_views.py
@@ -116,3 +116,94 @@ def test_confirm_post_handles_vpc_failure(client):
resp = client.post(reverse('identify_confirm'), {'match_idx': '0'})
assert resp.status_code == 302
assert client.session['identify_vpc_results'] == []
+
+
+from plants.models import Plant, Species
+
+
+def _set_fields_session(client, vpc_results=None):
+ session = client.session
+ session['identify_selected'] = {
+ 'scientific_name': 'Liatris spicata',
+ 'common_names': ['Blazing star', 'Pronkster'],
+ 'score': 0.94, 'gbif_id': '123', 'family': 'Asteraceae', 'genus': 'Liatris',
+ }
+ session['identify_vpc_results'] = vpc_results if vpc_results is not None else [
+ {'slug': 'liatris-spicata', 'common_name': 'Liatris spicata', 'scientific_name': 'Liatris spicata', 'thumbnail_url': '', 'source': 'vpc'},
+ ]
+ session['identify_vpc_idx'] = 0
+ session['identify_matches'] = []
+ session['identify_image_paths'] = []
+ session.save()
+
+
+@pytest.mark.django_db
+def test_fields_get_with_session(client):
+ _set_fields_session(client)
+ resp = client.get(reverse('identify_fields'))
+ assert resp.status_code == 200
+ assert b'Liatris spicata' in resp.content
+
+
+@pytest.mark.django_db
+def test_fields_post_creates_species_and_plant(client):
+ _set_fields_session(client)
+ with patch('plants.views.identify.default_storage') as mock_storage:
+ mock_storage.exists.return_value = False
+ with patch('plants.views.identify._apply_vpc_care_fields'):
+ resp = client.post(reverse('identify_fields'), {
+ 'common_name_source': 'plantnet',
+ 'scientific_name_source': 'plantnet',
+ 'name': 'Liatris',
+ })
+ assert resp.status_code == 302
+ assert Plant.objects.filter(name='Liatris').exists()
+ species = Species.objects.get(scientific_name='Liatris spicata')
+ assert species.common_name == 'Blazing star'
+
+
+@pytest.mark.django_db
+def test_fields_post_deduplicates_species(client):
+ Species.objects.create(scientific_name='Liatris spicata', common_name='Old name')
+ _set_fields_session(client)
+ with patch('plants.views.identify.default_storage') as mock_storage:
+ mock_storage.exists.return_value = False
+ with patch('plants.views.identify._apply_vpc_care_fields'):
+ client.post(reverse('identify_fields'), {
+ 'common_name_source': 'plantnet',
+ 'scientific_name_source': 'plantnet',
+ 'name': 'Liatris',
+ })
+ assert Species.objects.filter(scientific_name='Liatris spicata').count() == 1
+
+
+@pytest.mark.django_db
+def test_fields_post_clears_session(client):
+ _set_fields_session(client)
+ with patch('plants.views.identify.default_storage') as mock_storage:
+ mock_storage.exists.return_value = False
+ with patch('plants.views.identify._apply_vpc_care_fields'):
+ client.post(reverse('identify_fields'), {
+ 'common_name_source': 'plantnet',
+ 'scientific_name_source': 'plantnet',
+ 'name': 'Liatris',
+ })
+ assert 'identify_selected' not in client.session
+
+
+@pytest.mark.django_db
+def test_fields_post_uses_vpc_common_name(client):
+ _set_fields_session(client, vpc_results=[
+ {'slug': 'liatris-spicata-kobold', 'common_name': "Liatris 'Kobold'",
+ 'scientific_name': 'Liatris spicata', 'thumbnail_url': '', 'source': 'vpc'},
+ ])
+ with patch('plants.views.identify.default_storage') as mock_storage:
+ mock_storage.exists.return_value = False
+ with patch('plants.views.identify._apply_vpc_care_fields'):
+ client.post(reverse('identify_fields'), {
+ 'common_name_source': 'vpc',
+ 'scientific_name_source': 'plantnet',
+ 'name': 'Liatris Kobold',
+ })
+ species = Species.objects.get(scientific_name='Liatris spicata')
+ assert species.common_name == "Liatris 'Kobold'"