A simple to-do app focused on tasks that can be completed within a specific time span.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

filter tags while editing todo

ToBinio afba7f2e f7cfe8de

+68 -25
+1 -1
app/components/Edit/DataSelect.vue
··· 108 108 <h2 class="text-muted-text text-lg">{{ t("categories") }}</h2> 109 109 <CategorySelect v-model:category="category" /> 110 110 <h2 class="text-muted-text text-lg">{{ t("tags") }}</h2> 111 - <TagSelect v-model:tags="tags" :show-all="true" /> 111 + <TagSelect v-model:tags="tags" :category="category" /> 112 112 </TabsContent> 113 113 114 114 <TabsContent class="flex h-full flex-col justify-center" value="date">
+1 -1
app/components/Filter/FilterSheet.vue
··· 28 28 </div> 29 29 <div> 30 30 <h2 class="text-muted-text text-lg">{{ t("tags") }}</h2> 31 - <TagSelect v-model:tags="tags" :show-all="false" /> 31 + <TagSelect v-model:tags="tags" /> 32 32 </div> 33 33 </div> 34 34 </Sheet>
-6
app/components/Filter/TagSelect.vue
··· 6 6 7 7 const selectedTags = defineModel<UUID[]>("tags", { required: true }); 8 8 9 - const props = defineProps<{ showAll: boolean }>(); 10 - 11 9 const tagStore = useTagStore(); 12 10 13 11 function onPress(tag: UUID) { ··· 25 23 const filteredTodos = useFilteredTodos(); 26 24 27 25 const tags = computed(() => { 28 - if (props.showAll) { 29 - return tagStore.data; 30 - } 31 - 32 26 const activeTags = filteredTodos.value.flatMap((todo) => todo.tags); 33 27 const tagCount = activeTags.reduce( 34 28 (acc, id) => {
+1 -1
app/components/Nav/VerticalNav.vue
··· 27 27 <Icon name="material-symbols:bookmark" /> 28 28 {{ t("tags") }} 29 29 </h2> 30 - <TagSelect v-model:tags="tags" :show-all="false" /> 30 + <TagSelect v-model:tags="tags" /> 31 31 </div> 32 32 </div> 33 33 <div class="flex gap-1">
+55 -12
app/components/Utils/Label/TagSelect.vue
··· 1 1 <script setup lang="ts"> 2 - import { useFilteredTodos } from "~/composables/useFilteredTodos"; 2 + import { filterTodos } from "~/composables/useFilteredTodos"; 3 3 import { useTagStore } from "~/stores/useTagStore"; 4 4 import type { Label as LabelType, UUID } from "~~/shared/types"; 5 5 import TagLabel from "./TagLabel.vue"; 6 6 7 + const { t } = useI18n(); 8 + 7 9 const selectedTags = defineModel<UUID[]>("tags", { required: true }); 8 10 9 - const props = defineProps<{ showAll: boolean }>(); 11 + const props = defineProps<{ category: UUID | undefined }>(); 10 12 11 13 const tagStore = useTagStore(); 14 + const todoStore = useTodoStore(); 12 15 13 16 function onPress(tag: UUID) { 14 17 if (selectedTags.value!.includes(tag)) { ··· 22 25 return selectedTags.value!.includes(tag.uuid); 23 26 } 24 27 25 - const filteredTodos = useFilteredTodos(); 28 + const filteredTodos = computed(() => { 29 + return filterTodos(todoStore.data, { 30 + time: "all", 31 + tags: selectedTags.value, 32 + category: props.category ? [props.category] : [], 33 + }); 34 + }); 26 35 27 36 const tags = computed(() => { 28 - if (props.showAll) { 29 - return tagStore.data; 30 - } 31 - 32 37 const activeTags = filteredTodos.value.flatMap((todo) => todo.tags); 33 - const tagCount = activeTags.reduce( 38 + const activeTagCount = activeTags.reduce( 34 39 (acc, id) => { 35 40 acc[id] = (acc[id] || 0) + 1; 36 41 return acc; ··· 38 43 {} as Record<UUID, number>, 39 44 ); 40 45 41 - return tagStore.data 42 - .filter((tag) => tagCount[tag.uuid]! > 0) 46 + let filteredTags = tagStore.data 47 + .filter((tag) => activeTagCount[tag.uuid]! > 0) 48 + .sort((a, b) => { 49 + const diff = 50 + (activeTagCount[b.uuid] ?? 0) - (activeTagCount[a.uuid] ?? 0); 51 + if (diff !== 0) return diff; 52 + 53 + return a.name.localeCompare(b.name); 54 + }); 55 + 56 + const tagCount = todoStore.data 57 + .flatMap((todo) => todo.tags) 58 + .reduce( 59 + (acc, id) => { 60 + acc[id] = (acc[id] || 0) + 1; 61 + return acc; 62 + }, 63 + {} as Record<UUID, number>, 64 + ); 65 + let otherTags = tagStore.data 66 + .filter((tag) => !filteredTags.includes(tag)) 43 67 .sort((a, b) => { 44 - const diff = tagCount[b.uuid]! - tagCount[a.uuid]!; 68 + const diff = (tagCount[b.uuid] ?? 0) - (tagCount[a.uuid] ?? 0); 45 69 if (diff !== 0) return diff; 46 70 47 71 return a.name.localeCompare(b.name); 48 72 }); 73 + 74 + return { filteredTags, otherTags }; 49 75 }); 50 76 </script> 51 77 52 78 <template> 53 79 <div class="overflow-auto"> 54 80 <TagLabel 55 - v-for="tag in tags" 81 + v-for="tag in tags.filteredTags" 56 82 :key="tag.uuid" 57 83 :label="tag" 58 84 type="tag" ··· 60 86 class="mr-1 mb-1" 61 87 @press="onPress(tag.uuid)" 62 88 /> 89 + <div> 90 + <div 91 + v-if="tags.otherTags.length !== 0 && tags.filteredTags.length !== 0" 92 + class="text-sm text-muted-text" 93 + > 94 + {{ t("tagSelect.notUsedYet") }} 95 + </div> 96 + <TagLabel 97 + v-for="tag in tags.otherTags" 98 + :key="tag.uuid" 99 + :label="tag" 100 + type="tag" 101 + :is-selected="isSelected(tag)" 102 + class="mr-1 mb-1" 103 + @press="onPress(tag.uuid)" 104 + /> 105 + </div> 63 106 </div> 64 107 </template>
+2 -2
app/composables/useFilteredTodos.ts
··· 11 11 const todoStore = useTodoStore(); 12 12 const { tags, category, time } = useFilter(); 13 13 14 - const filterdTodos = computed(() => { 14 + const filteredTodos = computed(() => { 15 15 return filterTodos(todoStore.data, { 16 16 time: time.value, 17 17 tags: tags.value, ··· 19 19 }); 20 20 }); 21 21 22 - return filterdTodos; 22 + return filteredTodos; 23 23 } 24 24 25 25 export function filterTodos(todos: Todo[], filter: Filter) {
+4 -1
i18n/locales/de.json
··· 30 30 "date-point": "Zeitpunkt", 31 31 "recurring-none": "Keine", 32 32 "recurring-daily": "Täglich", 33 - "recurring-weekly": "Wöchentlich" 33 + "recurring-weekly": "Wöchentlich", 34 + "tagSelect": { 35 + "notUsedYet": "Nicht verwendet" 36 + } 34 37 }
+4 -1
i18n/locales/en.json
··· 30 30 "date-point": "Date Point", 31 31 "recurring-none": "None", 32 32 "recurring-daily": "Daily", 33 - "recurring-weekly": "Weekly" 33 + "recurring-weekly": "Weekly", 34 + "tagSelect": { 35 + "notUsedYet": "Not used yet" 36 + } 34 37 }