fix: Nuxt3 upgrades UI fixes & improvements (#5589)
Some checks are pending
CodeQL / Analyze (push) Waiting to run
Docker Nightly Production / Backend Server Tests (push) Waiting to run
Docker Nightly Production / Frontend Tests (push) Waiting to run
Docker Nightly Production / Build Package (push) Waiting to run
Docker Nightly Production / Build Tagged Release (push) Blocked by required conditions
Docker Nightly Production / Notify Discord (push) Blocked by required conditions
Release Drafter / ✏️ Draft release (push) Waiting to run

This commit is contained in:
Arsène Reymond 2025-06-28 15:59:58 +02:00 committed by GitHub
parent 2fb5dac966
commit 084f99b0de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 137 additions and 133 deletions

View file

@ -24,8 +24,7 @@
<v-container <v-container
v-if="book" v-if="book"
fluid class="my-0"
class="py-0 my-0"
> >
<v-sheet <v-sheet
color="transparent" color="transparent"
@ -33,13 +32,12 @@
elevation="0" elevation="0"
> >
<div class="d-flex align-center w-100 mb-2"> <div class="d-flex align-center w-100 mb-2">
<v-toolbar-title class="headline mb-0">
<v-icon size="large" class="mr-3"> <v-icon size="large" class="mr-3">
{{ $globals.icons.pages }} {{ $globals.icons.pages }}
</v-icon> </v-icon>
<v-toolbar-title class="headline mb-0">
{{ book.name }} {{ book.name }}
</v-toolbar-title> </v-toolbar-title>
<v-spacer />
<BaseButton <BaseButton
v-if="canEdit" v-if="canEdit"
class="mx-1" class="mx-1"

View file

@ -69,22 +69,22 @@ export default defineNuxtComponent({
const i18n = useI18n(); const i18n = useI18n();
const MEAL_TYPE_OPTIONS = [ const MEAL_TYPE_OPTIONS = [
{ text: i18n.t("meal-plan.breakfast"), value: "breakfast" }, { title: i18n.t("meal-plan.breakfast"), value: "breakfast" },
{ text: i18n.t("meal-plan.lunch"), value: "lunch" }, { title: i18n.t("meal-plan.lunch"), value: "lunch" },
{ text: i18n.t("meal-plan.dinner"), value: "dinner" }, { title: i18n.t("meal-plan.dinner"), value: "dinner" },
{ text: i18n.t("meal-plan.side"), value: "side" }, { title: i18n.t("meal-plan.side"), value: "side" },
{ text: i18n.t("meal-plan.type-any"), value: "unset" }, { title: i18n.t("meal-plan.type-any"), value: "unset" },
]; ];
const MEAL_DAY_OPTIONS = [ const MEAL_DAY_OPTIONS = [
{ text: i18n.t("general.monday"), value: "monday" }, { title: i18n.t("general.monday"), value: "monday" },
{ text: i18n.t("general.tuesday"), value: "tuesday" }, { title: i18n.t("general.tuesday"), value: "tuesday" },
{ text: i18n.t("general.wednesday"), value: "wednesday" }, { title: i18n.t("general.wednesday"), value: "wednesday" },
{ text: i18n.t("general.thursday"), value: "thursday" }, { title: i18n.t("general.thursday"), value: "thursday" },
{ text: i18n.t("general.friday"), value: "friday" }, { title: i18n.t("general.friday"), value: "friday" },
{ text: i18n.t("general.saturday"), value: "saturday" }, { title: i18n.t("general.saturday"), value: "saturday" },
{ text: i18n.t("general.sunday"), value: "sunday" }, { title: i18n.t("general.sunday"), value: "sunday" },
{ text: i18n.t("meal-plan.day-any"), value: "unset" }, { title: i18n.t("meal-plan.day-any"), value: "unset" },
]; ];
const inputDay = computed({ const inputDay = computed({

View file

@ -189,6 +189,7 @@
:show-add="false" :show-add="false"
:show-label="false" :show-label="false"
:show-icon="false" :show-icon="false"
variant="underlined"
@update:model-value="setOrganizerValues(field, index, $event)" @update:model-value="setOrganizerValues(field, index, $event)"
/> />
<RecipeOrganizerSelector <RecipeOrganizerSelector
@ -198,6 +199,7 @@
:show-add="false" :show-add="false"
:show-label="false" :show-label="false"
:show-icon="false" :show-icon="false"
variant="underlined"
@update:model-value="setOrganizerValues(field, index, $event)" @update:model-value="setOrganizerValues(field, index, $event)"
/> />
<RecipeOrganizerSelector <RecipeOrganizerSelector
@ -207,6 +209,7 @@
:show-add="false" :show-add="false"
:show-label="false" :show-label="false"
:show-icon="false" :show-icon="false"
variant="underlined"
@update:model-value="setOrganizerValues(field, index, $event)" @update:model-value="setOrganizerValues(field, index, $event)"
/> />
<RecipeOrganizerSelector <RecipeOrganizerSelector
@ -216,6 +219,7 @@
:show-add="false" :show-add="false"
:show-label="false" :show-label="false"
:show-icon="false" :show-icon="false"
variant="underlined"
@update:model-value="setOrganizerValues(field, index, $event)" @update:model-value="setOrganizerValues(field, index, $event)"
/> />
<RecipeOrganizerSelector <RecipeOrganizerSelector
@ -225,6 +229,7 @@
:show-add="false" :show-add="false"
:show-label="false" :show-label="false"
:show-icon="false" :show-icon="false"
variant="underlined"
@update:model-value="setOrganizerValues(field, index, $event)" @update:model-value="setOrganizerValues(field, index, $event)"
/> />
</v-col> </v-col>

View file

@ -74,6 +74,7 @@
:size="$vuetify.display.xs ? 'small' : undefined" :size="$vuetify.display.xs ? 'small' : undefined"
:color="btn.color" :color="btn.color"
variant="elevated" variant="elevated"
:icon="$vuetify.display.xs"
@click="emitHandler(btn.event)" @click="emitHandler(btn.event)"
> >
<v-icon :left="!$vuetify.display.xs"> <v-icon :left="!$vuetify.display.xs">

View file

@ -10,7 +10,7 @@
v-for="category in items.slice(0, limit)" v-for="category in items.slice(0, limit)"
:key="category.name" :key="category.name"
label label
class="ma-1" class="mr-1 mt-1"
color="accent" color="accent"
variant="flat" variant="flat"
:size="small ? 'small' : 'default'" :size="small ? 'small' : 'default'"

View file

@ -17,7 +17,7 @@
id="arrow-search" id="arrow-search"
v-model="search.query.value" v-model="search.query.value"
autofocus autofocus
variant="solo-filled" variant="solo"
flat flat
autocomplete="off" autocomplete="off"
bg-color="primary-lighten-1" bg-color="primary-lighten-1"

View file

@ -1,7 +1,7 @@
<template> <template>
<v-container <v-container
fluid fluid
class="pa-0" class="px-0"
> >
<div class="search-container pb-8"> <div class="search-container pb-8">
<form <form

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="ma-0 pa-0 text-subtitle-1 dense-markdown ingredient-item"> <div class="text-subtitle-1 dense-markdown ingredient-item">
<SafeMarkdown <SafeMarkdown
v-if="parsedIng.quantity" v-if="parsedIng.quantity"
class="d-inline" class="d-inline"

View file

@ -28,6 +28,7 @@
</template> </template>
<v-list-item <v-list-item
density="compact" density="compact"
class="pa-0"
@click.stop="toggleChecked(index)" @click.stop="toggleChecked(index)"
> >
<template #prepend> <template #prepend>

View file

@ -59,7 +59,7 @@
<v-app-bar <v-app-bar
color="transparent" color="transparent"
flat flat
class="mt-n1 rounded align-center px-4 position-relative w-100 left-0 top-0" class="mt-n1 rounded align-center position-relative w-100 left-0 top-0"
> >
<v-icon <v-icon
size="large" size="large"

View file

@ -9,9 +9,9 @@
closable-chips closable-chips
item-title="name" item-title="name"
multiple multiple
variant="underlined" :variant="variant"
:prepend-inner-icon="icon" :prepend-inner-icon="icon"
:append-icon="$globals.icons.create" :append-icon="showAdd ? $globals.icons.create : undefined"
return-object return-object
auto-select-first auto-select-first
class="pa-0" class="pa-0"
@ -93,6 +93,10 @@ export default defineNuxtComponent({
type: Boolean, type: Boolean,
default: true, default: true,
}, },
variant: {
type: String as () => "filled" | "underlined" | "outlined" | "plain" | "solo" | "solo-inverted" | "solo-filled",
default: "outlined",
},
}, },
emits: ["update:modelValue"], emits: ["update:modelValue"],

View file

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<v-container v-show="!isCookMode" key="recipe-page" class="pt-0" :class="{ 'pa-0': $vuetify.display.smAndDown.value }"> <v-container v-show="!isCookMode" key="recipe-page" class="px-0" :class="{ 'pa-0': $vuetify.display.smAndDown.value }">
<v-card :flat="$vuetify.display.smAndDown.value" class="d-print-none"> <v-card :flat="$vuetify.display.smAndDown.value" class="d-print-none">
<RecipePageHeader <RecipePageHeader
:recipe="recipe" :recipe="recipe"
@ -87,11 +87,10 @@
/> />
<RecipePrintContainer :recipe="recipe" :scale="scale" /> <RecipePrintContainer :recipe="recipe" :scale="scale" />
</v-container> </v-container>
<!-- Cook mode displayes two columns with ingredients and instructions side by side, each being scrolled individually, allowing to view both at the same timer --> <!-- Cook mode displayes two columns with ingredients and instructions side by side, each being scrolled individually, allowing to view both at the same time -->
<v-sheet <v-sheet
v-show="isCookMode && !hasLinkedIngredients" v-show="isCookMode && !hasLinkedIngredients"
key="cookmode" key="cookmode"
:style="{ height: $vuetify.display.smAndUp ? 'calc(100vh - 48px)' : '' }"
> >
<!-- the calc is to account for the toolbar a more dynamic solution could be needed --> <!-- the calc is to account for the toolbar a more dynamic solution could be needed -->
<v-row style="height: 100%" no-gutters class="overflow-hidden"> <v-row style="height: 100%" no-gutters class="overflow-hidden">
@ -107,7 +106,12 @@
/> />
<v-divider /> <v-divider />
</v-col> </v-col>
<v-col class="overflow-y-auto py-2" style="height: 100%" cols="12" sm="7"> <v-col class="overflow-y-auto"
:class="$vuetify.display.smAndDown.value ? 'py-2': 'py-6'"
style="height: 100%" cols="12" sm="7">
<h2 class="text-h5 px-4 font-weight-medium opacity-80">
{{ $t('recipe.instructions') }}
</h2>
<RecipePageInstructions <RecipePageInstructions
v-model="recipe.recipeInstructions" v-model="recipe.recipeInstructions"
v-model:assets="recipe.assets" v-model:assets="recipe.assets"

View file

@ -1,31 +1,28 @@
<template> <template>
<div class="d-flex justify-start align-top py-2"> <div class="d-flex justify-start align-top flex-wrap">
<RecipeImageUploadBtn <RecipeImageUploadBtn
class="my-1" class="my-2"
:slug="recipe.slug" :slug="recipe.slug"
@upload="uploadImage" @upload="uploadImage"
@refresh="imageKey++" @refresh="imageKey++"
/> />
<RecipeSettingsMenu <RecipeSettingsMenu
v-model="recipe.settings" v-model="recipe.settings"
class="my-1 mx-1" class="my-2 mx-1"
:is-owner="recipe.userId == user.id" :is-owner="recipe.userId == user.id"
@upload="uploadImage" @upload="uploadImage"
/> />
<v-spacer /> <v-spacer />
<v-container
class="py-0"
style="width: 40%;"
>
<v-select <v-select
v-model="recipe.userId" v-model="recipe.userId"
class="my-2"
max-width="300"
:items="allUsers" :items="allUsers"
item-title="fullName" :item-props="itemsProps"
item-value="id"
:label="$t('general.owner')" :label="$t('general.owner')"
hide-details
:disabled="!canEditOwner" :disabled="!canEditOwner"
variant="underlined" variant="outlined"
density="compact"
> >
<template #prepend> <template #prepend>
<UserAvatar <UserAvatar
@ -34,17 +31,7 @@
/> />
</template> </template>
</v-select> </v-select>
<v-card-text </div>
v-if="ownerHousehold"
class="pa-0 d-flex"
style="align-items: flex-end;"
>
<v-spacer />
<v-icon>{{ $globals.icons.household }}</v-icon>
<span class="pl-1">{{ ownerHousehold.name }}</span>
</v-card-text>
</v-container>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -71,13 +58,15 @@ const canEditOwner = computed(() => {
const { store: allUsers } = useUserStore(); const { store: allUsers } = useUserStore();
const { store: households } = useHouseholdStore(); const { store: households } = useHouseholdStore();
const ownerHousehold = computed(() => {
const owner = allUsers.value.find(u => u.id === recipe.value.userId); function itemsProps(item: any) {
if (!owner) { const owner = allUsers.value.find(u => u.id === item.id);
return null; return {
} value: item.id,
return households.value.find(h => h.id === owner.householdId); title: item.fullName,
}); subtitle: owner ? households.value.find(h => h.id === owner.householdId)?.name || "" : "",
};
}
async function uploadImage(fileObject: File) { async function uploadImage(fileObject: File) {
if (!recipe.value || !recipe.value.slug) { if (!recipe.value || !recipe.value.slug) {

View file

@ -11,15 +11,17 @@
class="d-flex flex-column justify-center align-center" class="d-flex flex-column justify-center align-center"
> >
<v-card-text class="w-100"> <v-card-text class="w-100">
<v-card-title class="text-h5 font-weight-regular pa-0 d-flex flex-column align-center justify-center opacity-80"> <div class="d-flex flex-column align-center">
<v-card-title class="text-h5 font-weight-regular pa-0 text-wrap text-center opacity-80">
{{ recipe.name }} {{ recipe.name }}
<RecipeRating </v-card-title>
<RecipeRating
:key="recipe.slug" :key="recipe.slug"
:value="recipe.rating" :value="recipe.rating"
:recipe-id="recipe.id" :recipe-id="recipe.id"
:slug="recipe.slug" :slug="recipe.slug"
/> />
</v-card-title> </div>
<v-divider class="my-2" /> <v-divider class="my-2" />
<SafeMarkdown :source="recipe.description" class="my-3" /> <SafeMarkdown :source="recipe.description" class="my-3" />
<v-divider v-if="recipe.description" /> <v-divider v-if="recipe.description" />
@ -52,7 +54,7 @@
</v-col> </v-col>
</v-row> </v-row>
</div> </div>
<div class="mx-6"> <div v-if="recipe.prepTime || recipe.totalTime || recipe.performTime" class="mx-6">
<RecipeTimeCard <RecipeTimeCard
container-class="d-flex flex-wrap justify-center" container-class="d-flex flex-wrap justify-center"
:prep-time="recipe.prepTime" :prep-time="recipe.prepTime"

View file

@ -15,12 +15,13 @@
v-for="(tool, index) in recipe.tools" v-for="(tool, index) in recipe.tools"
:key="index" :key="index"
density="compact" density="compact"
class="px-1"
> >
<template #prepend> <template #prepend>
<v-checkbox <v-checkbox
v-model="recipeTools[index].onHand" v-model="recipeTools[index].onHand"
hide-details hide-details
class="pt-0 my-auto py-auto" class="pt-0 py-auto"
color="secondary" color="secondary"
density="compact" density="compact"
@change="updateTool(index)" @change="updateTool(index)"

View file

@ -60,7 +60,7 @@
{{ $t('tool.required-tools') }} {{ $t('tool.required-tools') }}
</v-card-title> </v-card-title>
<v-divider class="mx-2" /> <v-divider class="mx-2" />
<v-card-text class="pt-0"> <v-card-text>
<RecipeOrganizerSelector <RecipeOrganizerSelector
v-model="recipe.tools" v-model="recipe.tools"
selector-type="tools" selector-type="tools"

View file

@ -141,6 +141,9 @@ export default defineNuxtComponent({
</script> </script>
<style scoped> <style scoped>
.text-center {
font-size: smaller;
}
.time-card-flex { .time-card-flex {
width: fit-content; width: fit-content;
} }

View file

@ -125,6 +125,7 @@
<v-alert <v-alert
type="info" type="info"
:text="$t('search.no-results')" :text="$t('search.no-results')"
class="mb-0"
/> />
</div> </div>
</v-card-text> </v-card-text>

View file

@ -32,11 +32,11 @@
<v-row> <v-row>
<v-col cols="9"> <v-col cols="9">
<v-text-field <v-text-field
v-model="generatedSignupLink"
:label="$t('profile.invite-link')" :label="$t('profile.invite-link')"
type="text" type="text"
readonly readonly
variant="filled" variant="filled"
:value="generatedSignupLink"
/> />
</v-col> </v-col>
<v-col <v-col

View file

@ -86,9 +86,8 @@ import { usePasswordField } from "~/composables/use-passwords";
import UserPasswordStrength from "~/components/Domain/User/UserPasswordStrength.vue"; import UserPasswordStrength from "~/components/Domain/User/UserPasswordStrength.vue";
const inputAttrs = { const inputAttrs = {
rounded: true,
validateOnBlur: true, validateOnBlur: true,
class: "rounded-lg pb-1", class: "pb-1",
variant: "solo-filled" as any, variant: "solo-filled" as any,
}; };

View file

@ -105,7 +105,7 @@
</v-list-item> </v-list-item>
</template> </template>
</AppSidebar> </AppSidebar>
<v-main class="pt-16"> <v-main class="pt-12">
<v-scroll-x-transition> <v-scroll-x-transition>
<div> <div>
<NuxtPage /> <NuxtPage />

View file

@ -10,7 +10,6 @@
<v-col <v-col
v-for="(inputField, index) in items" v-for="(inputField, index) in items"
:key="index" :key="index"
class="py-0"
cols="12" cols="12"
sm="12" sm="12"
> >
@ -75,7 +74,6 @@
:disabled="(inputField.disableUpdate && updateMode) || (!updateMode && inputField.disableCreate) || (disabledFields && disabledFields.includes(inputField.varName))" :disabled="(inputField.disableUpdate && updateMode) || (!updateMode && inputField.disableCreate) || (disabledFields && disabledFields.includes(inputField.varName))"
variant="solo-filled" variant="solo-filled"
flat flat
class="rounded-lg"
rows="3" rows="3"
auto-grow auto-grow
density="comfortable" density="comfortable"
@ -95,7 +93,6 @@
:disabled="(inputField.disableUpdate && updateMode) || (!updateMode && inputField.disableCreate) || (disabledFields && disabledFields.includes(inputField.varName))" :disabled="(inputField.disableUpdate && updateMode) || (!updateMode && inputField.disableCreate) || (disabledFields && disabledFields.includes(inputField.varName))"
variant="solo-filled" variant="solo-filled"
flat flat
class="rounded-lg"
:prepend-icon="inputField.icons ? modelValue[inputField.varName] : null" :prepend-icon="inputField.icons ? modelValue[inputField.varName] : null"
:label="inputField.label" :label="inputField.label"
:name="inputField.varName" :name="inputField.varName"

View file

@ -10,6 +10,7 @@
<v-card-title class="text-h5 pl-0 py-0" style="font-weight: normal;"> <v-card-title class="text-h5 pl-0 py-0" style="font-weight: normal;">
<v-icon <v-icon
v-if="icon" v-if="icon"
size="small"
start start
> >
{{ icon }} {{ icon }}
@ -24,7 +25,7 @@
<slot /> <slot />
</p> </p>
</v-card-text> </v-card-text>
<v-divider class="mb-3" /> <v-divider class="mt-1 mb-3" />
</v-card> </v-card>
</template> </template>

View file

@ -29,7 +29,6 @@
<v-toolbar-title class="headline"> <v-toolbar-title class="headline">
{{ title }} {{ title }}
</v-toolbar-title> </v-toolbar-title>
<v-spacer />
</v-toolbar> </v-toolbar>
<v-progress-linear <v-progress-linear
v-if="loading" v-if="loading"

View file

@ -10,7 +10,7 @@
style="margin-bottom: 4rem" style="margin-bottom: 4rem"
dark dark
> >
<v-toolbar-title class="headline text-h4"> <v-toolbar-title class="headline text-h4 text-center mx-0">
Mealie Mealie
</v-toolbar-title> </v-toolbar-title>
</v-toolbar> </v-toolbar>

View file

@ -10,7 +10,6 @@
:min="min" :min="min"
:max="max" :max="max"
type="number" type="number"
class="rounded-xl"
size="small" size="small"
variant="plain" variant="plain"
/> />

View file

@ -150,6 +150,7 @@ import {
mdiCodeTags, mdiCodeTags,
mdiKnife, mdiKnife,
mdiCookie, mdiCookie,
mdiBellPlus,
} from "@mdi/js"; } from "@mdi/js";
export const icons = { export const icons = {
@ -174,6 +175,7 @@ export const icons = {
arrowUpDown: mdiDrag, arrowUpDown: mdiDrag,
backupRestore: mdiBackupRestore, backupRestore: mdiBackupRestore,
bellAlert: mdiBellAlert, bellAlert: mdiBellAlert,
bellPlus: mdiBellPlus,
broom: mdiBroom, broom: mdiBroom,
calendar: mdiCalendar, calendar: mdiCalendar,
calendarMinus: mdiCalendarMinus, calendarMinus: mdiCalendarMinus,

View file

@ -26,7 +26,7 @@
<section> <section>
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.wrench" :title="$t('admin.maintenance.summary-title')" /> <BaseCardSectionTitle class="pb-0" :icon="$globals.icons.wrench" :title="$t('admin.maintenance.summary-title')" />
<div class="mb-6 ml-2 d-flex" style="gap: 0.3rem"> <div class="mb-6 d-flex" style="gap: 0.3rem">
<BaseButton color="info" @click="getSummary"> <BaseButton color="info" @click="getSummary">
<template #icon> <template #icon>
{{ $globals.icons.tools }} {{ $globals.icons.tools }}
@ -40,7 +40,7 @@
{{ $t("admin.maintenance.button-label-open-details") }} {{ $t("admin.maintenance.button-label-open-details") }}
</BaseButton> </BaseButton>
</div> </div>
<v-card class="ma-2" :loading="state.fetchingInfo"> <v-card class="" :loading="state.fetchingInfo">
<template v-for="(value, idx) in info" :key="`item-${idx}`"> <template v-for="(value, idx) in info" :key="`item-${idx}`">
<v-list-item> <v-list-item>
<v-list-item-title class="py-2"> <v-list-item-title class="py-2">
@ -67,21 +67,23 @@
</template> </template>
</i18n-t> </i18n-t>
</BaseCardSectionTitle> </BaseCardSectionTitle>
<v-card class="ma-2" :loading="state.actionLoading"> <v-card class="ma-0" flat :loading="state.actionLoading">
<template v-for="(action, idx) in actions" :key="`item-${idx}`"> <template v-for="(action, idx) in actions" :key="`item-${idx}`">
<v-list-item class="py-1"> <v-list-item class="py-2 px-0">
<v-list-item-title> <v-list-item-title>
<div>{{ action.name }}</div> <div>{{ action.name }}</div>
<v-list-item-subtitle class="wrap-word"> <v-list-item-subtitle class="wrap-word">
{{ action.subtitle }} {{ action.subtitle }}
</v-list-item-subtitle> </v-list-item-subtitle>
</v-list-item-title> </v-list-item-title>
<BaseButton color="info" @click="action.handler"> <template #append>
<BaseButton color="info" @click="action.handler">
<template #icon> <template #icon>
{{ $globals.icons.robot }} {{ $globals.icons.robot }}
</template> </template>
{{ $t("general.run") }} {{ $t("general.run") }}
</BaseButton> </BaseButton>
</template>
</v-list-item> </v-list-item>
<v-divider class="mx-2" /> <v-divider class="mx-2" />
</template> </template>

View file

@ -33,7 +33,6 @@
:items="groups" :items="groups"
variant="solo-filled" variant="solo-filled"
flat flat
class="rounded-lg"
item-title="name" item-title="name"
item-value="id" item-value="id"
:return-object="false" :return-object="false"

View file

@ -12,8 +12,6 @@
v-if="groups" v-if="groups"
v-model="createHouseholdForm.data.groupId" v-model="createHouseholdForm.data.groupId"
:items="groups" :items="groups"
rounded
class="rounded-lg"
item-title="name" item-title="name"
item-value="id" item-value="id"
:return-object="false" :return-object="false"

View file

@ -24,8 +24,6 @@
v-if="groups" v-if="groups"
v-model="selectedGroupId" v-model="selectedGroupId"
:items="groups" :items="groups"
rounded
class="rounded-lg"
item-title="name" item-title="name"
item-value="id" item-value="id"
:return-object="false" :return-object="false"
@ -37,8 +35,6 @@
v-model="newUserData.household" v-model="newUserData.household"
:disabled="!selectedGroupId" :disabled="!selectedGroupId"
:items="households" :items="households"
rounded
class="rounded-lg"
item-title="name" item-title="name"
item-value="name" item-value="name"
:return-object="false" :return-object="false"

View file

@ -17,10 +17,10 @@
<v-form @submit.prevent="requestLink()"> <v-form @submit.prevent="requestLink()">
<v-text-field <v-text-field
v-model="email" v-model="email"
variant="filled" :prepend-inner-icon="$globals.icons.email"
rounded variant="solo-filled"
flat
autofocus autofocus
class="rounded-lg"
name="login" name="login"
:label="$t('user.email')" :label="$t('user.email')"
type="text" type="text"

View file

@ -7,7 +7,7 @@
<v-card-text> <v-card-text>
{{ $t('recipe.recipe-bulk-importer-description') }} {{ $t('recipe.recipe-bulk-importer-description') }}
</v-card-text> </v-card-text>
</div> <div class="px-4">
<section class="mt-2"> <section class="mt-2">
<v-row <v-row
v-for="(_, idx) in bulkUrls" v-for="(_, idx) in bulkUrls"
@ -54,6 +54,7 @@
cols="12" cols="12"
xs="12" xs="12"
sm="6" sm="6"
class="py-0"
> >
<RecipeOrganizerSelector <RecipeOrganizerSelector
v-model="bulkUrls[idx].categories" v-model="bulkUrls[idx].categories"
@ -73,6 +74,7 @@
cols="12" cols="12"
xs="12" xs="12"
sm="6" sm="6"
class="pt-0 pb-4"
> >
<RecipeOrganizerSelector <RecipeOrganizerSelector
v-model="bulkUrls[idx].tags" v-model="bulkUrls[idx].tags"
@ -90,8 +92,9 @@
</v-col> </v-col>
</template> </template>
</v-row> </v-row>
<v-card-actions class="justify-end flex-wrap mb-1"> <v-card-actions class="justify-end flex-wrap mt-3 pa-0">
<BaseButton <BaseButton
class="mt-1 pr-4"
delete delete
@click=" @click="
bulkUrls = []; bulkUrls = [];
@ -117,23 +120,26 @@
@bulk-data="assignUrls" @bulk-data="assignUrls"
/> />
</v-card-actions> </v-card-actions>
<div class="px-1"> <div class="px-0">
<v-checkbox <v-checkbox
v-model="showCatTags" v-model="showCatTags"
hide-details hide-details
:label="$t('recipe.set-categories-and-tags')" :label="$t('recipe.set-categories-and-tags')"
/> />
</div> </div>
<v-card-actions class="justify-end"> <v-card-actions class="justify-center">
<div style="width: 250px">
<BaseButton <BaseButton
:disabled="bulkUrls.length === 0 || lockBulkImport" :disabled="bulkUrls.length === 0 || lockBulkImport"
rounded
block
@click="bulkCreate" @click="bulkCreate"
> >
<template #icon> <template #icon>
{{ $globals.icons.check }} {{ $globals.icons.check }}
</template> </template>
{{ $t('general.submit') }}
</BaseButton> </BaseButton>
</div>
</v-card-actions> </v-card-actions>
</section> </section>
<section class="mt-12"> <section class="mt-12">
@ -144,6 +150,8 @@
/> />
</section> </section>
</div> </div>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">

View file

@ -61,7 +61,6 @@
<div style="width: 250px"> <div style="width: 250px">
<BaseButton <BaseButton
:disabled="!newRecipeData" :disabled="!newRecipeData"
large
rounded rounded
block block
type="submit" type="submit"

View file

@ -25,7 +25,6 @@
<div style="width: 250px"> <div style="width: 250px">
<BaseButton <BaseButton
:disabled="newRecipeZip === null" :disabled="newRecipeZip === null"
large
rounded rounded
block block
:loading="loading" :loading="loading"

View file

@ -2,7 +2,7 @@
<div> <div>
<BasePageTitle <BasePageTitle
v-if="groupName" v-if="groupName"
class="bg-grey-darken-4 mt-n4 pt-8" class="mt-n4 pt-8"
> >
<template #header> <template #header>
<v-img <v-img

View file

@ -15,11 +15,12 @@
</template> </template>
{{ $t('migration.recipe-data-migrations-explanation') }} {{ $t('migration.recipe-data-migrations-explanation') }}
</BasePageTitle> </BasePageTitle>
<v-container> <v-container :class="$vuetify.display.smAndDown ? 'px-0': ''">
<BaseCardSectionTitle :title="$t('migration.new-migration')" /> <BaseCardSectionTitle :title="$t('migration.new-migration')" />
<v-card <v-card
variant="outlined" variant="outlined"
:loading="loading" :loading="loading"
style="border-color: lightgrey;"
> >
<v-card-title> {{ $t('migration.choose-migration-type') }} </v-card-title> <v-card-title> {{ $t('migration.choose-migration-type') }} </v-card-title>
<v-card-text <v-card-text
@ -83,7 +84,7 @@
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-container> </v-container>
<v-container> <v-container class="$vuetify.display.smAndDown ? 'px-0': ''">
<BaseCardSectionTitle :title="$t('migration.previous-migrations')" /> <BaseCardSectionTitle :title="$t('migration.previous-migrations')" />
<ReportTable <ReportTable
:items="reports" :items="reports"

View file

@ -15,6 +15,7 @@
<BaseDialog <BaseDialog
v-model="createDialog" v-model="createDialog"
:title="$t('events.new-notification')" :title="$t('events.new-notification')"
:icon="$globals.icons.bellPlus"
can-submit can-submit
@submit="createNewNotifier" @submit="createNewNotifier"
> >
@ -95,7 +96,7 @@
> >
<v-expansion-panel-title <v-expansion-panel-title
disable-icon-rotate disable-icon-rotate
class="headline" class="text-h6"
> >
<div class="d-flex align-center"> <div class="d-flex align-center">
{{ notifier.name }} {{ notifier.name }}
@ -103,6 +104,7 @@
<template #actions> <template #actions>
<v-btn <v-btn
icon icon
flat
class="ml-2" class="ml-2"
> >
<v-icon> <v-icon>

View file

@ -47,7 +47,7 @@
<!-- Form Container --> <!-- Form Container -->
<div class="d-flex justify-center grow items-center my-4"> <div class="d-flex justify-center grow items-center my-4">
<template v-if="state.ctx.state === States.Initial"> <template v-if="state.ctx.state === States.Initial">
<div width="600px"> <v-container>
<v-card-title class="text-h5 my-4 mb-5 pb-0 text-center"> <v-card-title class="text-h5 my-4 mb-5 pb-0 text-center">
{{ $t("user-registration.user-registration") }} {{ $t("user-registration.user-registration") }}
</v-card-title> </v-card-title>
@ -60,7 +60,7 @@
color="primary" color="primary"
dark dark
hover hover
width="300px" width="320px"
@click="initial.joinGroup" @click="initial.joinGroup"
> >
<v-card-title class="d-flex align-center justify-center py-3"> <v-card-title class="d-flex align-center justify-center py-3">
@ -77,7 +77,7 @@
color="primary" color="primary"
dark dark
hover hover
width="300px" width="320px"
@click="initial.createGroup" @click="initial.createGroup"
> >
<v-card-title class="d-flex align-center justify-center py-3"> <v-card-title class="d-flex align-center justify-center py-3">
@ -92,7 +92,7 @@
</v-card-title> </v-card-title>
</v-card> </v-card>
</div> </div>
</div> </v-container>
</template> </template>
<template v-else-if="state.ctx.state === States.ProvideToken"> <template v-else-if="state.ctx.state === States.ProvideToken">
@ -333,9 +333,7 @@ import type { VForm } from "~/types/auto-forms";
const inputAttrs = { const inputAttrs = {
variant: "filled", variant: "filled",
rounded: true,
validateOnBlur: true, validateOnBlur: true,
class: "rounded-lg",
}; };
export default defineNuxtComponent({ export default defineNuxtComponent({

View file

@ -17,21 +17,19 @@
<v-form @submit.prevent="requestLink()"> <v-form @submit.prevent="requestLink()">
<v-text-field <v-text-field
v-model="email" v-model="email"
:prepend-icon="$globals.icons.email" :prepend-inner-icon="$globals.icons.email"
variant="filled" variant="solo-filled"
rounded flat
autofocus autofocus
class="rounded-lg"
name="login" name="login"
:label="$t('user.email')" :label="$t('user.email')"
type="text" type="text"
/> />
<v-text-field <v-text-field
v-model="password" v-model="password"
variant="filled" variant="solo-filled"
rounded flat
class="rounded-lg" :prepend-inner-icon="$globals.icons.lock"
:prepend-icon="$globals.icons.lock"
name="password" name="password"
:label="$t('user.password')" :label="$t('user.password')"
type="password" type="password"
@ -39,11 +37,10 @@
/> />
<v-text-field <v-text-field
v-model="passwordConfirm" v-model="passwordConfirm"
variant="filled" variant="solo-filled"
rounded flat
validate-on="blur" validate-on="blur"
class="rounded-lg" :prepend-inner-icon="$globals.icons.lock"
:prepend-icon="$globals.icons.lock"
name="password" name="password"
:label="$t('user.confirm-password')" :label="$t('user.confirm-password')"
type="password" type="password"

View file

@ -17,9 +17,10 @@
<section class="d-flex justify-center"> <section class="d-flex justify-center">
<v-card <v-card
class="mt-4" class="mt-4"
width="500px" width="100%"
flat
> >
<v-card-text> <v-card-text class="px-0">
<v-form <v-form
ref="domNewTokenForm" ref="domNewTokenForm"
@submit.prevent @submit.prevent
@ -38,16 +39,16 @@
readonly readonly
rows="3" rows="3"
/> />
<v-list-subheader class="text-center"> <p>
{{ {{
$t( $t(
"settings.token.copy-this-token-for-use-with-an-external-application-this-token-will-not-be-viewable-again", "settings.token.copy-this-token-for-use-with-an-external-application-this-token-will-not-be-viewable-again",
) )
}} }}
</v-list-subheader> </p>
</template> </template>
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions class="px-0">
<BaseButton <BaseButton
v-if="createdToken" v-if="createdToken"
cancel cancel
@ -78,14 +79,11 @@
:title="$t('settings.token.active-tokens')" :title="$t('settings.token.active-tokens')"
/> />
<section class="d-flex flex-column"> <section class="d-flex flex-column">
<v-list>
<div <div
v-for="(token, index) in user.tokens" v-for="(token, index) in user.tokens"
:key="index" :key="index"
> >
<v-card
variant="outlined"
class="mb-2"
>
<v-list-item> <v-list-item>
<v-list-item-title> <v-list-item-title>
{{ token.name }} {{ token.name }}
@ -93,16 +91,17 @@
<v-list-item-subtitle> <v-list-item-subtitle>
{{ $t('general.created-on-date', [$d(new Date(token.createdAt!))]) }} {{ $t('general.created-on-date', [$d(new Date(token.createdAt!))]) }}
</v-list-item-subtitle> </v-list-item-subtitle>
<v-list-item-action> <template #append>
<BaseButton <BaseButton
delete delete
small small
@click="deleteToken(token.id)" @click="deleteToken(token.id)"
/> />
</v-list-item-action> </template>
</v-list-item> </v-list-item>
</v-card> <v-divider class="mx-2 my-2" />
</div> </div>
</v-list>
</section> </section>
</v-container> </v-container>
</template> </template>

View file

@ -1,5 +1,5 @@
<template> <template>
<v-container v-if="user"> <v-container v-if="user" class="mb-8">
<section class="d-flex flex-column align-center mt-4"> <section class="d-flex flex-column align-center mt-4">
<UserAvatar <UserAvatar
:tooltip="false" :tooltip="false"
@ -7,7 +7,7 @@
:user-id="user.id" :user-id="user.id"
/> />
<h2 class="text-h4"> <h2 class="text-h4 text-center">
{{ $t('profile.welcome-user', [user.fullName]) }} {{ $t('profile.welcome-user', [user.fullName]) }}
</h2> </h2>
<p class="subtitle-1 mb-0 text-center"> <p class="subtitle-1 mb-0 text-center">