1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-02 20:15:24 +02:00

feat: Migrate to Nuxt 3 framework (#5184)

Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
This commit is contained in:
Hoa (Kyle) Trinh 2025-06-20 00:09:12 +07:00 committed by GitHub
parent 89ab7fac25
commit c24d532608
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
403 changed files with 23959 additions and 19557 deletions

View file

@ -1,7 +1,6 @@
import { Ref, useContext } from "@nuxtjs/composition-api";
import { useLocalStorage, useSessionStorage } from "@vueuse/core";
import { RegisteredParser, TimelineEventType } from "~/lib/api/types/recipe";
import { QueryFilterJSON } from "~/lib/api/types/response";
import type { RegisteredParser, TimelineEventType } from "~/lib/api/types/recipe";
import type { QueryFilterJSON } from "~/lib/api/types/response";
export interface UserPrintPreferences {
imagePosition: string;
@ -67,7 +66,7 @@ export function useUserMealPlanPreferences(): Ref<UserMealPlanPreferences> {
{
numberOfDays: 7,
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserMealPlanPreferences>;
@ -83,7 +82,7 @@ export function useUserPrintPreferences(): Ref<UserPrintPreferences> {
showDescription: true,
showNotes: true,
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserPrintPreferences>;
@ -92,7 +91,7 @@ export function useUserPrintPreferences(): Ref<UserPrintPreferences> {
}
export function useUserSortPreferences(): Ref<UserRecipePreferences> {
const { $globals } = useContext();
const { $globals } = useNuxtApp();
const fromStorage = useLocalStorage(
"recipe-section-preferences",
@ -103,7 +102,7 @@ export function useUserSortPreferences(): Ref<UserRecipePreferences> {
sortIcon: $globals.icons.sortAlphabeticalAscending,
useMobileCards: false,
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserRecipePreferences>;
@ -117,7 +116,7 @@ export function useUserSearchQuerySession(): Ref<UserSearchQuery> {
{
recipe: "",
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserSearchQuery>;
@ -125,7 +124,6 @@ export function useUserSearchQuerySession(): Ref<UserSearchQuery> {
return fromStorage;
}
export function useShoppingListPreferences(): Ref<UserShoppingListPreferences> {
const fromStorage = useLocalStorage(
"shopping-list-preferences",
@ -133,7 +131,7 @@ export function useShoppingListPreferences(): Ref<UserShoppingListPreferences> {
viewAllLists: false,
viewByLabel: true,
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserShoppingListPreferences>;
@ -148,7 +146,7 @@ export function useTimelinePreferences(): Ref<UserTimelinePreferences> {
orderDirection: "asc",
types: ["info", "system", "comment"] as TimelineEventType[],
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserTimelinePreferences>;
@ -162,7 +160,7 @@ export function useParsingPreferences(): Ref<UserParsingPreferences> {
{
parser: "nlp",
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserParsingPreferences>;
@ -176,7 +174,7 @@ export function useCookbookPreferences(): Ref<UserCookbooksPreferences> {
{
hideOtherHouseholds: false,
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserCookbooksPreferences>;
@ -197,7 +195,7 @@ export function useRecipeFinderPreferences(): Ref<UserRecipeFinderPreferences> {
includeFoodsOnHand: true,
includeToolsOnHand: true,
},
{ mergeDefaults: true }
{ 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 unknown as Ref<UserRecipeFinderPreferences>;

View file

@ -1,78 +1,77 @@
import { useContext } from "@nuxtjs/composition-api";
import { fieldTypes } from "../forms";
import { AutoFormItems } from "~/types/auto-forms";
import type { AutoFormItems } from "~/types/auto-forms";
export const useUserForm = () => {
const { i18n } = useContext();
const i18n = useI18n();
const userForm: AutoFormItems = [
{
section: i18n.tc("user.user-details"),
label: i18n.tc("user.user-name"),
section: i18n.t("user.user-details"),
label: i18n.t("user.user-name"),
varName: "username",
type: fieldTypes.TEXT,
rules: ["required"],
},
{
label: i18n.tc("user.full-name"),
label: i18n.t("user.full-name"),
varName: "fullName",
type: fieldTypes.TEXT,
rules: ["required"],
},
{
label: i18n.tc("user.email"),
label: i18n.t("user.email"),
varName: "email",
type: fieldTypes.TEXT,
rules: ["required"],
},
{
label: i18n.tc("user.password"),
label: i18n.t("user.password"),
varName: "password",
disableUpdate: true,
type: fieldTypes.PASSWORD,
rules: ["required", "minLength:8"],
},
{
label: i18n.tc("user.authentication-method"),
label: i18n.t("user.authentication-method"),
varName: "authMethod",
type: fieldTypes.SELECT,
hint: i18n.tc("user.authentication-method-hint"),
hint: i18n.t("user.authentication-method-hint"),
disableCreate: true,
options: [{ text: "Mealie" }, { text: "LDAP" }, { text: "OIDC" }],
},
{
section: i18n.tc("user.permissions"),
label: i18n.tc("user.administrator"),
section: i18n.t("user.permissions"),
label: i18n.t("user.administrator"),
varName: "admin",
type: fieldTypes.BOOLEAN,
rules: ["required"],
},
{
label: i18n.tc("user.user-can-invite-other-to-group"),
label: i18n.t("user.user-can-invite-other-to-group"),
varName: "canInvite",
type: fieldTypes.BOOLEAN,
rules: ["required"],
},
{
label: i18n.tc("user.user-can-manage-group"),
label: i18n.t("user.user-can-manage-group"),
varName: "canManage",
type: fieldTypes.BOOLEAN,
rules: ["required"],
},
{
label: i18n.tc("user.user-can-organize-group-data"),
label: i18n.t("user.user-can-organize-group-data"),
varName: "canOrganize",
type: fieldTypes.BOOLEAN,
rules: ["required"],
},
{
label: i18n.tc("user.user-can-manage-household"),
label: i18n.t("user.user-can-manage-household"),
varName: "canManageHousehold",
type: fieldTypes.BOOLEAN,
rules: ["required"],
},
{
label: i18n.tc("user.enable-advanced-features"),
label: i18n.t("user.enable-advanced-features"),
varName: "advanced",
type: fieldTypes.BOOLEAN,
rules: ["required"],

View file

@ -1,17 +1,16 @@
import { ref, useContext } from "@nuxtjs/composition-api";
import { useUserApi } from "~/composables/api";
import { UserRatingSummary } from "~/lib/api/types/user";
import type { UserRatingSummary } from "~/lib/api/types/user";
const userRatings = ref<UserRatingSummary[]>([]);
const loading = ref(false);
const ready = ref(false);
export const useUserSelfRatings = function () {
const { $auth } = useContext();
const $auth = useMealieAuth();
const api = useUserApi();
async function refreshUserRatings() {
if (!$auth.user || loading.value) {
if (!$auth.user.value || loading.value) {
return;
}
@ -24,7 +23,7 @@ export const useUserSelfRatings = function () {
async function setRating(slug: string, rating: number | null, isFavorite: boolean | null) {
loading.value = true;
const userId = $auth.user?.id || "";
const userId = $auth.user.value?.id || "";
await api.users.setRating(userId, slug, rating, isFavorite);
loading.value = false;
await refreshUserRatings();
@ -39,5 +38,5 @@ export const useUserSelfRatings = function () {
refreshUserRatings,
setRating,
ready,
}
}
};
};

View file

@ -1,6 +1,5 @@
import { ref, Ref, useContext } from "@nuxtjs/composition-api";
import { useAsyncValidator } from "~/composables/use-validators";
import { VForm } from "~/types/vuetify";
import type { VForm } from "~/types/vuetify";
import { usePublicApi } from "~/composables/api/api-client";
const domAccountForm = ref<VForm | null>(null);
@ -12,7 +11,8 @@ const password2 = ref("");
const advancedOptions = ref(false);
export const useUserRegistrationForm = () => {
const { i18n } = useContext();
const i18n = useI18n();
function safeValidate(form: Ref<VForm | null>) {
if (form.value && form.value.validate) {
return form.value.validate();
@ -29,15 +29,15 @@ export const useUserRegistrationForm = () => {
const { validate: validateUsername, valid: validUsername } = useAsyncValidator(
username,
(v: string) => publicApi.validators.username(v),
i18n.tc("validation.username-is-taken"),
usernameErrorMessages
i18n.t("validation.username-is-taken"),
usernameErrorMessages,
);
const emailErrorMessages = ref<string[]>([]);
const { validate: validateEmail, valid: validEmail } = useAsyncValidator(
email,
(v: string) => publicApi.validators.email(v),
i18n.tc("validation.email-is-taken"),
emailErrorMessages
i18n.t("validation.email-is-taken"),
emailErrorMessages,
);
const accountDetails = {
username,
@ -60,7 +60,7 @@ export const useUserRegistrationForm = () => {
};
// ================================================================
// Provide Credentials
const passwordMatch = () => password1.value === password2.value || i18n.tc("user.password-must-match");
const passwordMatch = () => password1.value === password2.value || i18n.t("user.password-must-match");
const credentials = {
password1,
password2,
@ -68,7 +68,7 @@ export const useUserRegistrationForm = () => {
reset: () => {
credentials.password1.value = "";
credentials.password2.value = "";
}
},
};
return {