Frontend overhaul: NetBox-style detail pages, selectable columns, data sources
- Cultivar/species detail pages rewritten with two-column card layout, attribute tables, em-dash placeholders
- Column toggle + per-page selector on all list pages (families, species, cultivars, suppliers)
- Species list: table/card view toggle with family, layer, N-fixer, uses columns
- Cultivar detail: supplier links with SKU/price/product URL, species info section
- Data sources page (/sources) with attribution for all 10 data sources
- Fixed Cultivar/Species structs with #[serde(default)] for API compatibility
- Added table_controls component (reusable column toggle + per-page selector)
- Removed max-width constraint on content area for full-width tables
- Fixed route conflicts: merged {slug}/{id} into single {ref} routes
- Removed PostgreSQL enum types (plant_layer, drought_tolerance, etc.) in favor of TEXT
- Fixed API per_page parameter support across all list endpoints
This commit is contained in:
@@ -14,28 +14,28 @@ CREATE TABLE species (
|
||||
description TEXT,
|
||||
soil_moisture TEXT,
|
||||
drainage_requirement TEXT,
|
||||
organic_matter_pct NUMERIC(5,2),
|
||||
organic_matter_pct DOUBLE PRECISION,
|
||||
nitrogen_ppm INTEGER,
|
||||
phosphorus_ppm INTEGER,
|
||||
potassium_ppm INTEGER,
|
||||
boron_ppm NUMERIC(8,2),
|
||||
boron_ppm DOUBLE PRECISION,
|
||||
calcium_ppm INTEGER,
|
||||
copper_ppm NUMERIC(8,2),
|
||||
iron_ppm NUMERIC(8,2),
|
||||
copper_ppm DOUBLE PRECISION,
|
||||
iron_ppm DOUBLE PRECISION,
|
||||
magnesium_ppm INTEGER,
|
||||
manganese_ppm NUMERIC(8,2),
|
||||
molybdenum_ppm NUMERIC(8,2),
|
||||
manganese_ppm DOUBLE PRECISION,
|
||||
molybdenum_ppm DOUBLE PRECISION,
|
||||
sulfur_ppm INTEGER,
|
||||
zinc_ppm NUMERIC(8,2),
|
||||
ph_min NUMERIC(4,2),
|
||||
ph_max NUMERIC(4,2),
|
||||
zinc_ppm DOUBLE PRECISION,
|
||||
ph_min DOUBLE PRECISION,
|
||||
ph_max DOUBLE PRECISION,
|
||||
soil_texture_preference TEXT[],
|
||||
hardiness_zone_usda TEXT,
|
||||
hardiness_zone_at TEXT,
|
||||
min_temp NUMERIC(5,2),
|
||||
max_temp NUMERIC(5,2),
|
||||
min_temp DOUBLE PRECISION,
|
||||
max_temp DOUBLE PRECISION,
|
||||
drought_tolerance drought_tolerance,
|
||||
water_requirement_mm_week NUMERIC(5,2),
|
||||
water_requirement_mm_week DOUBLE PRECISION,
|
||||
waterlogging_tolerance BOOLEAN,
|
||||
salt_tolerance salt_tolerance,
|
||||
edibility_rating SMALLINT,
|
||||
|
||||
@@ -12,27 +12,27 @@ CREATE TABLE cultivars (
|
||||
is_organic BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
perennial BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
growing_time_days INTEGER,
|
||||
planting_depth_cm NUMERIC(5,2),
|
||||
row_spacing_cm NUMERIC(5,2),
|
||||
plant_spacing_cm NUMERIC(5,2),
|
||||
planting_depth_cm DOUBLE PRECISION,
|
||||
row_spacing_cm DOUBLE PRECISION,
|
||||
plant_spacing_cm DOUBLE PRECISION,
|
||||
days_to_germination INTEGER,
|
||||
germination_temp_c NUMERIC(5,2),
|
||||
germination_temp_c DOUBLE PRECISION,
|
||||
light_requirement TEXT,
|
||||
stratification_required BOOLEAN,
|
||||
stratification_days INTEGER,
|
||||
scarification_required BOOLEAN,
|
||||
seed_viability_years INTEGER,
|
||||
storage_temp_c NUMERIC(5,2),
|
||||
storage_temp_c DOUBLE PRECISION,
|
||||
storage_humidity TEXT,
|
||||
storage_notes TEXT,
|
||||
min_temp NUMERIC(5,2),
|
||||
max_temp NUMERIC(5,2),
|
||||
min_temp DOUBLE PRECISION,
|
||||
max_temp DOUBLE PRECISION,
|
||||
humidity TEXT,
|
||||
light TEXT,
|
||||
frost_tolerance frost_tolerance,
|
||||
min_light_hours_day NUMERIC(4,1),
|
||||
optimal_light_hours_day NUMERIC(4,1),
|
||||
greenhouse_min_temp_c NUMERIC(5,2),
|
||||
min_light_hours_day DOUBLE PRECISION,
|
||||
optimal_light_hours_day DOUBLE PRECISION,
|
||||
greenhouse_min_temp_c DOUBLE PRECISION,
|
||||
indoor_season_extension_weeks INTEGER,
|
||||
ventilation_requirement TEXT,
|
||||
heating_required BOOLEAN,
|
||||
@@ -48,9 +48,9 @@ CREATE TABLE cultivars (
|
||||
rootstock_species_id UUID REFERENCES species(id),
|
||||
years_to_first_harvest INTEGER,
|
||||
productive_lifespan_years INTEGER,
|
||||
expected_yield_kg_per_m2 NUMERIC(8,2),
|
||||
expected_yield_kg_per_m2 DOUBLE PRECISION,
|
||||
yield_unit TEXT,
|
||||
expected_yield_value NUMERIC(8,2),
|
||||
expected_yield_value DOUBLE PRECISION,
|
||||
harvest_window_days INTEGER,
|
||||
storage_method TEXT[],
|
||||
shelf_life_days INTEGER,
|
||||
|
||||
@@ -17,8 +17,8 @@ CREATE TABLE cultivar_suppliers (
|
||||
supplier_id UUID NOT NULL REFERENCES suppliers(id) ON DELETE CASCADE,
|
||||
article_number TEXT,
|
||||
product_url TEXT,
|
||||
price_eur NUMERIC(8,2),
|
||||
pack_size NUMERIC(8,2),
|
||||
price_eur DOUBLE PRECISION,
|
||||
pack_size DOUBLE PRECISION,
|
||||
pack_unit TEXT,
|
||||
last_checked_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
@@ -121,9 +121,9 @@ pub async fn create(pool: &PgPool, req: &CreateSpecies) -> Result<Species> {
|
||||
ground_cover_quality, allelopathic, guild_role, succession_stage, heavy_metal_tolerance,
|
||||
wikidata_qid, gbif_id, eppo_code, pfaf_url, source_urls)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,
|
||||
$17::drought_tolerance,$18::salt_tolerance,$19,$20,$21,$22,$23,
|
||||
$24::invasiveness_level,$25,$26::plant_layer,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,
|
||||
$37::succession_stage,$38,$39,$40,$41,$42,$43)
|
||||
$17,$18,$19,$20,$21,$22,$23,
|
||||
$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,
|
||||
$37,$38,$39,$40,$41,$42,$43)
|
||||
RETURNING *"
|
||||
)
|
||||
.bind(id).bind(&slug).bind(req.family_id).bind(&req.name_scientific)
|
||||
@@ -160,13 +160,13 @@ pub async fn update(pool: &PgPool, id: Uuid, req: &CreateSpecies) -> Result<Spec
|
||||
description=$7, soil_moisture=$8, drainage_requirement=$9, ph_min=$10, ph_max=$11,
|
||||
soil_texture_preference=$12, hardiness_zone_usda=$13, hardiness_zone_at=$14,
|
||||
min_temp=$15, max_temp=$16,
|
||||
drought_tolerance=$17::drought_tolerance, salt_tolerance=$18::salt_tolerance,
|
||||
drought_tolerance=$17, salt_tolerance=$18,
|
||||
edibility_rating=$19, food_uses=$20, medicinal_uses=$21, other_uses=$22,
|
||||
native_range=$23, invasiveness=$24::invasiveness_level, pollination_type=$25,
|
||||
plant_layer=$26::plant_layer, nitrogen_fixer=$27, dynamic_accumulator=$28,
|
||||
native_range=$23, invasiveness=$24, pollination_type=$25,
|
||||
plant_layer=$26, nitrogen_fixer=$27, dynamic_accumulator=$28,
|
||||
dynamic_accumulator_nutrients=$29, attracts_pollinators=$30, attracts_beneficial_insects=$31,
|
||||
wildlife_value=$32, mulch_plant=$33, ground_cover_quality=$34, allelopathic=$35,
|
||||
guild_role=$36, succession_stage=$37::succession_stage, heavy_metal_tolerance=$38,
|
||||
guild_role=$36, succession_stage=$37, heavy_metal_tolerance=$38,
|
||||
wikidata_qid=$39, gbif_id=$40, eppo_code=$41, pfaf_url=$42, source_urls=$43,
|
||||
updated_at=NOW()
|
||||
WHERE id=$1 RETURNING *"
|
||||
|
||||
Reference in New Issue
Block a user