feat: Add days in the past selector on meal planner (#6857)

Co-authored-by: Michael Genson <genson.michael@gmail.com>
This commit is contained in:
Arnas Savickas
2026-03-26 21:09:52 +02:00
committed by GitHub
parent 9f47f38176
commit 41c3f1fced
4 changed files with 33 additions and 7 deletions

View File

@@ -22,6 +22,7 @@ export enum ImagePosition {
} }
export interface UserMealPlanPreferences { export interface UserMealPlanPreferences {
numberOfDaysPast: number;
numberOfDays: number; numberOfDays: number;
} }
@@ -76,6 +77,7 @@ export function useUserMealPlanPreferences(): Ref<UserMealPlanPreferences> {
const fromStorage = useLocalStorage( const fromStorage = useLocalStorage(
"meal-planner-preferences", "meal-planner-preferences",
{ {
numberOfDaysPast: 0,
numberOfDays: 7, numberOfDays: 7,
}, },
{ mergeDefaults: true }, { mergeDefaults: true },

View File

@@ -331,6 +331,8 @@
"any-household": "Any Household", "any-household": "Any Household",
"no-meal-plan-defined-yet": "No meal plan defined yet", "no-meal-plan-defined-yet": "No meal plan defined yet",
"no-meal-planned-for-today": "No meal planned for today", "no-meal-planned-for-today": "No meal planned for today",
"numberOfDaysPast-hint": "Number of days in the past on page load",
"numberOfDaysPast-label": "Default Days in the Past",
"numberOfDays-hint": "Number of days on page load", "numberOfDays-hint": "Number of days on page load",
"numberOfDays-label": "Default Days", "numberOfDays-label": "Default Days",
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans", "only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans",
@@ -1471,4 +1473,4 @@
"min-length": "Must Be At Least {min} Characters", "min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters" "max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
} }
} }

View File

@@ -35,6 +35,18 @@
:local="$i18n.locale" :local="$i18n.locale"
/> />
<v-card-text>
<v-number-input
v-model="numberOfDaysPast"
:min="0"
control-variant="stacked"
inset
:label="$t('meal-plan.numberOfDaysPast-label')"
:hint="$t('meal-plan.numberOfDaysPast-hint')"
persistent-hint
/>
</v-card-text>
<v-card-text> <v-card-text>
<v-number-input <v-number-input
v-model="numberOfDays" v-model="numberOfDays"
@@ -111,7 +123,11 @@ useSeoMeta({
}); });
const mealPlanPreferences = useUserMealPlanPreferences(); const mealPlanPreferences = useUserMealPlanPreferences();
const numberOfDaysPast = ref<number>(mealPlanPreferences.value.numberOfDaysPast || 0);
const numberOfDays = ref<number>(mealPlanPreferences.value.numberOfDays || 7); const numberOfDays = ref<number>(mealPlanPreferences.value.numberOfDays || 7);
watch(numberOfDaysPast, (val) => {
mealPlanPreferences.value.numberOfDaysPast = Number(val);
});
watch(numberOfDays, (val) => { watch(numberOfDays, (val) => {
mealPlanPreferences.value.numberOfDays = Number(val); mealPlanPreferences.value.numberOfDays = Number(val);
}); });
@@ -135,7 +151,7 @@ function safeParseISO(date: string, fallback: Date | undefined = undefined) {
} }
// Initialize dates from query parameters or defaults // Initialize dates from query parameters or defaults
const initialStartDate = safeParseISO(route.query.start as string, new Date()); const initialStartDate = safeParseISO(route.query.start as string, addDays(new Date(), adjustForToday(-numberOfDaysPast.value)));
const initialEndDate = safeParseISO(route.query.end as string, addDays(new Date(), adjustForToday(numberOfDays.value))); const initialEndDate = safeParseISO(route.query.end as string, addDays(new Date(), adjustForToday(numberOfDays.value)));
const state = ref({ const state = ref({
@@ -163,7 +179,7 @@ const weekRange = computed(() => {
return { start, end }; return { start, end };
} }
return { return {
start: new Date(), start: addDays(new Date(), adjustForToday(-numberOfDaysPast.value)),
end: addDays(new Date(), adjustForToday(numberOfDays.value)), end: addDays(new Date(), adjustForToday(numberOfDays.value)),
}; };
}); });
@@ -193,9 +209,9 @@ function filterMealByDate(date: Date) {
} }
function adjustForToday(days: number) { function adjustForToday(days: number) {
// The use case for this function is "how many days are we adding to 'today'?" // e.g. If the user wants 7 days, we subtract one to do "today + 6"
// e.g. If the user wants 7 days, we substract one to do "today + 6" // e.g. If the user wants 2 days in the past, we keep it the same to do "today - 2"
return days > 0 ? days - 1 : days + 1; return days > 0 ? days - 1 : days;
} }
const days = computed(() => { const days = computed(() => {

View File

@@ -15,7 +15,7 @@
<v-container class="px-0 d-flex align-center" height="56px"> <v-container class="px-0 d-flex align-center" height="56px">
<v-row no-gutters style="width: 100%;"> <v-row no-gutters style="width: 100%;">
<v-col cols="10" class="d-flex align-center"> <v-col cols="10" class="d-flex align-center">
<p class="pl-2 my-1"> <p class="pl-2 my-1" :class="{ 'text-primary': isToday(day.date) }">
{{ $d(day.date, "short") }} {{ $d(day.date, "short") }}
</p> </p>
</v-col> </v-col>
@@ -51,6 +51,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { isSameDay } from "date-fns";
import type { MealsByDate } from "./types"; import type { MealsByDate } from "./types";
import type { ReadPlanEntry } from "~/lib/api/types/meal-plan"; import type { ReadPlanEntry } from "~/lib/api/types/meal-plan";
import GroupMealPlanDayContextMenu from "~/components/Domain/Household/GroupMealPlanDayContextMenu.vue"; import GroupMealPlanDayContextMenu from "~/components/Domain/Household/GroupMealPlanDayContextMenu.vue";
@@ -126,4 +128,8 @@ const plan = computed<Days[]>(() => {
return acc; return acc;
}, [] as Days[]); }, [] as Days[]);
}); });
const isToday = (date: Date) => {
return isSameDay(date, new Date());
};
</script> </script>