diff --git a/herbapi-api/migrations/010_species_bilingual_uses.sql b/herbapi-api/migrations/010_species_bilingual_uses.sql new file mode 100644 index 0000000..30e1130 --- /dev/null +++ b/herbapi-api/migrations/010_species_bilingual_uses.sql @@ -0,0 +1,6 @@ +ALTER TABLE species ADD COLUMN IF NOT EXISTS food_uses_de TEXT; +ALTER TABLE species ADD COLUMN IF NOT EXISTS food_uses_en TEXT; +ALTER TABLE species ADD COLUMN IF NOT EXISTS medicinal_uses_de TEXT; +ALTER TABLE species ADD COLUMN IF NOT EXISTS medicinal_uses_en TEXT; +ALTER TABLE species ADD COLUMN IF NOT EXISTS other_uses_de TEXT; +ALTER TABLE species ADD COLUMN IF NOT EXISTS other_uses_en TEXT; diff --git a/herbapi-api/src/db/models.rs b/herbapi-api/src/db/models.rs index 300cb63..e66b1c1 100644 --- a/herbapi-api/src/db/models.rs +++ b/herbapi-api/src/db/models.rs @@ -101,8 +101,14 @@ pub struct Species { pub salt_tolerance: Option, pub edibility_rating: Option, pub food_uses: Option, + pub food_uses_de: Option, + pub food_uses_en: Option, pub medicinal_uses: Option, + pub medicinal_uses_de: Option, + pub medicinal_uses_en: Option, pub other_uses: Option, + pub other_uses_de: Option, + pub other_uses_en: Option, pub native_range: Option, pub invasiveness: Option, pub pollination_type: Option, @@ -164,8 +170,14 @@ pub struct CreateSpecies { pub salt_tolerance: Option, pub edibility_rating: Option, pub food_uses: Option, + pub food_uses_de: Option, + pub food_uses_en: Option, pub medicinal_uses: Option, + pub medicinal_uses_de: Option, + pub medicinal_uses_en: Option, pub other_uses: Option, + pub other_uses_de: Option, + pub other_uses_en: Option, pub native_range: Option, pub invasiveness: Option, pub pollination_type: Option, diff --git a/herbapi-api/src/db/species.rs b/herbapi-api/src/db/species.rs index 0b5e782..ecd127d 100644 --- a/herbapi-api/src/db/species.rs +++ b/herbapi-api/src/db/species.rs @@ -106,7 +106,10 @@ pub async fn create(pool: &PgPool, req: &CreateSpecies) -> Result { soil_moisture, drainage_requirement, ph_min, ph_max, soil_texture_preference, hardiness_zone_usda, hardiness_zone_at, min_temp, max_temp, drought_tolerance, salt_tolerance, edibility_rating, - food_uses, medicinal_uses, other_uses, native_range, invasiveness, pollination_type, + food_uses, food_uses_de, food_uses_en, + medicinal_uses, medicinal_uses_de, medicinal_uses_en, + other_uses, other_uses_de, other_uses_en, + native_range, invasiveness, pollination_type, plant_layer, nitrogen_fixer, dynamic_accumulator, dynamic_accumulator_nutrients, attracts_pollinators, attracts_beneficial_insects, wildlife_value, mulch_plant, ground_cover_quality, allelopathic, guild_role, succession_stage, heavy_metal_tolerance, @@ -116,10 +119,10 @@ pub async fn create(pool: &PgPool, req: &CreateSpecies) -> Result { hoverfly_count, beetle_count, bird_count, mammal_count, native_status, naturadb_tags) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$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,$44,$45, - $46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58) + $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,$44, + $45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57, + $58,$59,$60,$61,$62,$63,$64) RETURNING *" ) .bind(id).bind(&slug).bind(req.family_id).bind(&req.name_scientific) @@ -130,7 +133,9 @@ pub async fn create(pool: &PgPool, req: &CreateSpecies) -> Result { .bind(&req.hardiness_zone_usda).bind(&req.hardiness_zone_at) .bind(req.min_temp).bind(req.max_temp) .bind(&req.drought_tolerance).bind(&req.salt_tolerance).bind(req.edibility_rating) - .bind(&req.food_uses).bind(&req.medicinal_uses).bind(&req.other_uses) + .bind(&req.food_uses).bind(&req.food_uses_de).bind(&req.food_uses_en) + .bind(&req.medicinal_uses).bind(&req.medicinal_uses_de).bind(&req.medicinal_uses_en) + .bind(&req.other_uses).bind(&req.other_uses_de).bind(&req.other_uses_en) .bind(&req.native_range).bind(&req.invasiveness).bind(&req.pollination_type) .bind(&req.plant_layer).bind(req.nitrogen_fixer).bind(req.dynamic_accumulator) .bind(&req.dynamic_accumulator_nutrients) @@ -165,17 +170,20 @@ pub async fn update(pool: &PgPool, id: Uuid, req: &CreateSpecies) -> Result Result Element { let sp_usda = opt_str(&sp.hardiness_zone_usda); let sp_nfix = opt_bool(sp.nitrogen_fixer); let sp_dynacc = opt_bool(sp.dynamic_accumulator); - let sp_food = opt_str(&sp.food_uses); - let sp_med = opt_str(&sp.medicinal_uses); - let sp_other = opt_str(&sp.other_uses); + let sp_food = pick_desc(¤t_lang, &sp.food_uses_de, &sp.food_uses_en, &sp.food_uses); + let sp_med = pick_desc(¤t_lang, &sp.medicinal_uses_de, &sp.medicinal_uses_en, &sp.medicinal_uses); + let sp_other = pick_desc(¤t_lang, &sp.other_uses_de, &sp.other_uses_en, &sp.other_uses); let sp_wildlife = opt_str(&sp.wildlife_value); let sp_native = opt_str(&sp.native_range); rsx! { diff --git a/herbapi-ui/src/pages/species.rs b/herbapi-ui/src/pages/species.rs index 1c1bf8e..707c873 100644 --- a/herbapi-ui/src/pages/species.rs +++ b/herbapi-ui/src/pages/species.rs @@ -496,9 +496,9 @@ pub fn SpeciesDetail(slug: String) -> Element { let desc = pick_desc(¤t_lang, &s.description_de, &s.description_en, &s.description); // Uses - let food = os(&s.food_uses); - let med = os(&s.medicinal_uses); - let other = os(&s.other_uses); + let food = pick_desc(¤t_lang, &s.food_uses_de, &s.food_uses_en, &s.food_uses); + let med = pick_desc(¤t_lang, &s.medicinal_uses_de, &s.medicinal_uses_en, &s.medicinal_uses); + let other = pick_desc(¤t_lang, &s.other_uses_de, &s.other_uses_en, &s.other_uses); let edibility = match s.edibility_rating { Some(r) => format!("{r}/5"), None => em.to_string(), diff --git a/herbapi-ui/src/types.rs b/herbapi-ui/src/types.rs index 09cb0b9..934c26c 100644 --- a/herbapi-ui/src/types.rs +++ b/herbapi-ui/src/types.rs @@ -43,8 +43,14 @@ pub struct Species { pub salt_tolerance: Option, pub edibility_rating: Option, pub food_uses: Option, + pub food_uses_de: Option, + pub food_uses_en: Option, pub medicinal_uses: Option, + pub medicinal_uses_de: Option, + pub medicinal_uses_en: Option, pub other_uses: Option, + pub other_uses_de: Option, + pub other_uses_en: Option, pub native_range: Option, pub plant_layer: Option, pub nitrogen_fixer: Option,