mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-11-01 10:43:25 -04:00
feat: Support User-Level Default Activities (#5125)
This commit is contained in:
63
frontend/composables/use-default-activity.ts
Normal file
63
frontend/composables/use-default-activity.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { Activity, I18n, TranslationResult } from "~/lib/api/types/activity";
|
||||
import { ActivityKey } from "~/lib/api/types/activity";
|
||||
|
||||
export const DEFAULT_ACTIVITY = "/g/home" as const;
|
||||
|
||||
type ActivityRegistry = {
|
||||
recipes: Activity;
|
||||
mealplanner: Activity;
|
||||
shopping_list: Activity;
|
||||
};
|
||||
|
||||
const selectableActivities: ActivityRegistry = {
|
||||
recipes: {
|
||||
key: ActivityKey.RECIPES,
|
||||
route: groupSlug => groupSlug ? `/g/${groupSlug}` : DEFAULT_ACTIVITY,
|
||||
label: i18n => i18n.t("general.recipes"),
|
||||
},
|
||||
mealplanner: {
|
||||
key: ActivityKey.MEALPLANNER,
|
||||
route: () => "/household/mealplan/planner/view",
|
||||
label: i18n => i18n.t("meal-plan.meal-planner"),
|
||||
},
|
||||
shopping_list: {
|
||||
key: ActivityKey.SHOPPING_LIST,
|
||||
route: () => "/shopping-lists",
|
||||
label: i18n => i18n.t("shopping-list.shopping-lists"),
|
||||
},
|
||||
};
|
||||
|
||||
function getDefaultActivityRoute(activityKey?: ActivityKey, groupSlug?: string): string {
|
||||
if (!activityKey) {
|
||||
return DEFAULT_ACTIVITY;
|
||||
}
|
||||
const route = selectableActivities[activityKey]?.route ?? (() => DEFAULT_ACTIVITY);
|
||||
return route(groupSlug);
|
||||
}
|
||||
|
||||
function getDefaultActivityLabels(i18n: I18n): TranslationResult[] {
|
||||
return Object.values(selectableActivities).map(
|
||||
({ label }) => label(i18n),
|
||||
);
|
||||
}
|
||||
|
||||
function getActivityKey(i18n: I18n, target: TranslationResult = ""): ActivityKey | undefined {
|
||||
return Object.values(selectableActivities)
|
||||
.find(({ label }) => label(i18n) === target)?.key;
|
||||
}
|
||||
|
||||
function getActivityLabel(i18n: I18n, target?: ActivityKey): TranslationResult {
|
||||
return Object.values(selectableActivities)
|
||||
.find(({ key }) => key === target)
|
||||
?.label(i18n) ?? "";
|
||||
}
|
||||
|
||||
export default function useDefaultActivity() {
|
||||
return {
|
||||
selectableActivities,
|
||||
getDefaultActivityRoute,
|
||||
getDefaultActivityLabels,
|
||||
getActivityKey,
|
||||
getActivityLabel,
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useLocalStorage, useSessionStorage } from "@vueuse/core";
|
||||
import { ActivityKey } from "~/lib/api/types/activity";
|
||||
import type { RegisteredParser, TimelineEventType } from "~/lib/api/types/recipe";
|
||||
import type { QueryFilterJSON } from "~/lib/api/types/response";
|
||||
|
||||
@@ -65,6 +66,10 @@ export interface UserRecipeCreatePreferences {
|
||||
parseRecipe: boolean;
|
||||
}
|
||||
|
||||
export interface UserActivityPreferences {
|
||||
defaultActivity: ActivityKey;
|
||||
}
|
||||
|
||||
export function useUserMealPlanPreferences(): Ref<UserMealPlanPreferences> {
|
||||
const fromStorage = useLocalStorage(
|
||||
"meal-planner-preferences",
|
||||
@@ -115,6 +120,20 @@ export function useUserSortPreferences(): Ref<UserRecipePreferences> {
|
||||
return fromStorage;
|
||||
}
|
||||
|
||||
export function useUserActivityPreferences(): Ref<UserActivityPreferences> {
|
||||
const fromStorage = useLocalStorage(
|
||||
"activity-preferences",
|
||||
{
|
||||
defaultActivity: ActivityKey.RECIPES,
|
||||
},
|
||||
{ mergeDefaults: true },
|
||||
// we cast to a Ref because by default it will return an optional type ref
|
||||
// but since we pass defaults we know all properties are set.
|
||||
) as Ref<UserActivityPreferences>;
|
||||
|
||||
return fromStorage;
|
||||
}
|
||||
|
||||
export function useUserSearchQuerySession(): Ref<UserSearchQuery> {
|
||||
const fromStorage = useSessionStorage(
|
||||
"search-query",
|
||||
|
||||
Reference in New Issue
Block a user