diff --git a/composeApp/src/main/kotlin/com/github/worn/ui/components/AddItemFields.kt b/composeApp/src/main/kotlin/com/github/worn/ui/components/AddItemFields.kt index 0357ff3..0b26e16 100644 --- a/composeApp/src/main/kotlin/com/github/worn/ui/components/AddItemFields.kt +++ b/composeApp/src/main/kotlin/com/github/worn/ui/components/AddItemFields.kt @@ -543,15 +543,16 @@ internal fun Subcategory.displayName(): String = stringResource( Subcategory.T_SHIRT -> R.string.subcategory_t_shirt Subcategory.POLO -> R.string.subcategory_polo Subcategory.DRESS_SHIRT -> R.string.subcategory_dress_shirt + Subcategory.LONG_SLEEVE_SHIRT -> R.string.subcategory_long_sleeve_shirt Subcategory.HENLEY -> R.string.subcategory_henley - Subcategory.SWEATER -> R.string.subcategory_sweater - Subcategory.HOODIE -> R.string.subcategory_hoodie Subcategory.JEANS -> R.string.subcategory_jeans Subcategory.CHINOS -> R.string.subcategory_chinos Subcategory.TAILORED_PANTS -> R.string.subcategory_tailored_pants Subcategory.SHORTS -> R.string.subcategory_shorts Subcategory.CARGO_PANTS -> R.string.subcategory_cargo_pants Subcategory.SWEATPANTS -> R.string.subcategory_sweatpants + Subcategory.SWEATER -> R.string.subcategory_sweater + Subcategory.HOODIE -> R.string.subcategory_hoodie Subcategory.BOMBER -> R.string.subcategory_bomber Subcategory.TRUCKER -> R.string.subcategory_trucker Subcategory.PUFFER -> R.string.subcategory_puffer diff --git a/composeApp/src/main/res/values-pt-rBR/strings.xml b/composeApp/src/main/res/values-pt-rBR/strings.xml index 1330868..ed91133 100644 --- a/composeApp/src/main/res/values-pt-rBR/strings.xml +++ b/composeApp/src/main/res/values-pt-rBR/strings.xml @@ -233,15 +233,16 @@ Camiseta Polo Camisa social + Camisa manga longa Henley - Suéter - Moletom Jeans Chinos Calça social Bermuda Calça cargo Calça de moletom + Suéter + Moletom Bomber Trucker Puffer diff --git a/composeApp/src/main/res/values/strings.xml b/composeApp/src/main/res/values/strings.xml index 6e25f47..34d3db2 100644 --- a/composeApp/src/main/res/values/strings.xml +++ b/composeApp/src/main/res/values/strings.xml @@ -233,15 +233,16 @@ T shirt Polo Dress shirt + Long sleeve shirt Henley - Sweater - Hoodie Jeans Chinos Tailored pants Shorts Cargo pants Sweatpants + Sweater + Hoodie Bomber Trucker Puffer diff --git a/iosApp/iosApp/en.lproj/Localizable.strings b/iosApp/iosApp/en.lproj/Localizable.strings index c4725e3..7223d92 100644 --- a/iosApp/iosApp/en.lproj/Localizable.strings +++ b/iosApp/iosApp/en.lproj/Localizable.strings @@ -230,15 +230,16 @@ "subcategory_t_shirt" = "T shirt"; "subcategory_polo" = "Polo"; "subcategory_dress_shirt" = "Dress shirt"; +"subcategory_long_sleeve_shirt" = "Long sleeve shirt"; "subcategory_henley" = "Henley"; -"subcategory_sweater" = "Sweater"; -"subcategory_hoodie" = "Hoodie"; "subcategory_jeans" = "Jeans"; "subcategory_chinos" = "Chinos"; "subcategory_tailored_pants" = "Tailored pants"; "subcategory_shorts" = "Shorts"; "subcategory_cargo_pants" = "Cargo pants"; "subcategory_sweatpants" = "Sweatpants"; +"subcategory_sweater" = "Sweater"; +"subcategory_hoodie" = "Hoodie"; "subcategory_bomber" = "Bomber"; "subcategory_trucker" = "Trucker"; "subcategory_puffer" = "Puffer"; diff --git a/iosApp/iosApp/pt-BR.lproj/Localizable.strings b/iosApp/iosApp/pt-BR.lproj/Localizable.strings index f6495eb..9c687c0 100644 --- a/iosApp/iosApp/pt-BR.lproj/Localizable.strings +++ b/iosApp/iosApp/pt-BR.lproj/Localizable.strings @@ -230,15 +230,16 @@ "subcategory_t_shirt" = "Camiseta"; "subcategory_polo" = "Polo"; "subcategory_dress_shirt" = "Camisa social"; +"subcategory_long_sleeve_shirt" = "Camisa manga longa"; "subcategory_henley" = "Henley"; -"subcategory_sweater" = "Suéter"; -"subcategory_hoodie" = "Moletom"; "subcategory_jeans" = "Jeans"; "subcategory_chinos" = "Chinos"; "subcategory_tailored_pants" = "Calça social"; "subcategory_shorts" = "Bermuda"; "subcategory_cargo_pants" = "Calça cargo"; "subcategory_sweatpants" = "Calça de moletom"; +"subcategory_sweater" = "Suéter"; +"subcategory_hoodie" = "Moletom"; "subcategory_bomber" = "Bomber"; "subcategory_trucker" = "Trucker"; "subcategory_puffer" = "Puffer"; diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index d8e3cd8..ded108f 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -78,7 +78,7 @@ sqldelight { databases { create("WardrobeDatabase") { packageName.set("com.github.worn.data.source.local.db") - version = 2 + version = 3 srcDirs("src/commonMain/sqldelight") } } diff --git a/shared/src/commonMain/kotlin/com/github/worn/data/source/ai/AiPrompts.kt b/shared/src/commonMain/kotlin/com/github/worn/data/source/ai/AiPrompts.kt index f14ac23..d7aa179 100644 --- a/shared/src/commonMain/kotlin/com/github/worn/data/source/ai/AiPrompts.kt +++ b/shared/src/commonMain/kotlin/com/github/worn/data/source/ai/AiPrompts.kt @@ -101,7 +101,7 @@ internal object AiPrompts { } } -private const val SUBCATEGORY_VALUES = "T_SHIRT, POLO, DRESS_SHIRT, HENLEY, SWEATER, HOODIE, " + - "JEANS, CHINOS, TAILORED_PANTS, SHORTS, CARGO_PANTS, SWEATPANTS, BOMBER, TRUCKER, PUFFER, " + - "BLAZER, COAT, WINDBREAKER, SNEAKERS, BOOTS_MILITARY, BOOTS_CHELSEA, DERBY, OXFORD, LOAFER, " + - "SANDALS, WATCH, BELT, SUNGLASSES, HAT_CAP, SCARF, BAG_BACKPACK" +private const val SUBCATEGORY_VALUES = "T_SHIRT, POLO, DRESS_SHIRT, LONG_SLEEVE_SHIRT, HENLEY, " + + "JEANS, CHINOS, TAILORED_PANTS, SHORTS, CARGO_PANTS, SWEATPANTS, SWEATER, HOODIE, BOMBER, " + + "TRUCKER, PUFFER, BLAZER, COAT, WINDBREAKER, SNEAKERS, BOOTS_MILITARY, BOOTS_CHELSEA, DERBY, " + + "OXFORD, LOAFER, SANDALS, WATCH, BELT, SUNGLASSES, HAT_CAP, SCARF, BAG_BACKPACK" diff --git a/shared/src/commonMain/kotlin/com/github/worn/domain/model/Subcategory.kt b/shared/src/commonMain/kotlin/com/github/worn/domain/model/Subcategory.kt index ee1240c..8a8241e 100644 --- a/shared/src/commonMain/kotlin/com/github/worn/domain/model/Subcategory.kt +++ b/shared/src/commonMain/kotlin/com/github/worn/domain/model/Subcategory.kt @@ -5,9 +5,8 @@ enum class Subcategory { T_SHIRT, POLO, DRESS_SHIRT, + LONG_SLEEVE_SHIRT, HENLEY, - SWEATER, - HOODIE, // BOTTOM JEANS, @@ -18,6 +17,8 @@ enum class Subcategory { SWEATPANTS, // OUTERWEAR + SWEATER, + HOODIE, BOMBER, TRUCKER, PUFFER, @@ -48,9 +49,8 @@ fun subcategoriesFor(category: Category): List = when (category) { Subcategory.T_SHIRT, Subcategory.POLO, Subcategory.DRESS_SHIRT, + Subcategory.LONG_SLEEVE_SHIRT, Subcategory.HENLEY, - Subcategory.SWEATER, - Subcategory.HOODIE, ) Category.BOTTOM -> listOf( Subcategory.JEANS, @@ -61,6 +61,8 @@ fun subcategoriesFor(category: Category): List = when (category) { Subcategory.SWEATPANTS, ) Category.OUTERWEAR -> listOf( + Subcategory.SWEATER, + Subcategory.HOODIE, Subcategory.BOMBER, Subcategory.TRUCKER, Subcategory.PUFFER, diff --git a/shared/src/commonMain/sqldelight/migrations/2.sqm b/shared/src/commonMain/sqldelight/migrations/2.sqm new file mode 100644 index 0000000..4bd60d1 --- /dev/null +++ b/shared/src/commonMain/sqldelight/migrations/2.sqm @@ -0,0 +1 @@ +UPDATE clothingItem SET category = 'OUTERWEAR' WHERE subcategory IN ('HOODIE', 'SWEATER'); diff --git a/shared/src/commonTest/kotlin/com/github/worn/model/SubcategoryTest.kt b/shared/src/commonTest/kotlin/com/github/worn/model/SubcategoryTest.kt new file mode 100644 index 0000000..02b54b3 --- /dev/null +++ b/shared/src/commonTest/kotlin/com/github/worn/model/SubcategoryTest.kt @@ -0,0 +1,39 @@ +package com.github.worn.model + +import com.github.worn.domain.model.Category +import com.github.worn.domain.model.Subcategory +import com.github.worn.domain.model.capsuleWardrobeSuggestions +import com.github.worn.domain.model.subcategoriesFor +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class SubcategoryTest { + + @Test + fun `every subcategory belongs to exactly one category`() { + val mapped = Category.entries.flatMap { subcategoriesFor(it) } + + assertEquals(mapped.size, mapped.toSet().size, "a subcategory is listed under more than one category") + assertEquals(Subcategory.entries.toSet(), mapped.toSet(), "a subcategory is missing from subcategoriesFor()") + } + + @Test + fun `hoodie and sweater are outerwear`() { + val outerwear = subcategoriesFor(Category.OUTERWEAR) + + assertTrue(Subcategory.HOODIE in outerwear) + assertTrue(Subcategory.SWEATER in outerwear) + } + + @Test + fun `capsule wardrobe suggestions pair each subcategory with its own category`() { + capsuleWardrobeSuggestions.forEach { suggestion -> + val subcategory = suggestion.subcategory ?: return@forEach + assertTrue( + subcategory in subcategoriesFor(suggestion.mappedCategory), + "${suggestion.itemName}: $subcategory is not a ${suggestion.mappedCategory} subcategory", + ) + } + } +}