mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-24 15:49:42 +02:00
feat: "I Made This" Dialog (#1801)
* added chef hat * removed unnecessary log * modified recipe and recipe timeline event schema changed timeline event "message" -> "event_message" added "last made" timestamp to recipe * added "I made this" dialog to recipe action menu * added missing field and re-ran code-gen * moved dialog out of context menu and refactored removed references in action menu and context menu refactored dialog to be triggered by a button instead added route to update recipe last made timestamp added visual for last made timestamp to recipe header and title * added sorting by last made * switched event type to comment * replaced alter column with pydantic alias * added tests for event message alias
This commit is contained in:
parent
f0e6496001
commit
a2dcdc1adf
20 changed files with 275 additions and 9 deletions
143
frontend/components/Domain/Recipe/RecipeLastMade.vue
Normal file
143
frontend/components/Domain/Recipe/RecipeLastMade.vue
Normal file
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<BaseDialog
|
||||
v-model="madeThisDialog"
|
||||
:icon="$globals.icons.chefHat"
|
||||
title="I Made This"
|
||||
:submit-text="$tc('general.save')"
|
||||
@submit="createTimelineEvent"
|
||||
>
|
||||
<v-card-text>
|
||||
<v-form ref="domMadeThisForm">
|
||||
<v-textarea
|
||||
v-model="newTimelineEvent.eventMessage"
|
||||
autofocus
|
||||
label="Comment"
|
||||
hint="How did it turn out?"
|
||||
persistent-hint
|
||||
rows="4"
|
||||
></v-textarea>
|
||||
<v-menu
|
||||
v-model="datePickerMenu"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
max-width="290px"
|
||||
min-width="auto"
|
||||
>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
v-model="newTimelineEvent.timestamp"
|
||||
:prepend-icon="$globals.icons.calendar"
|
||||
v-bind="attrs"
|
||||
readonly
|
||||
v-on="on"
|
||||
></v-text-field>
|
||||
</template>
|
||||
<v-date-picker v-model="newTimelineEvent.timestamp" no-title @input="datePickerMenu = false"></v-date-picker>
|
||||
</v-menu>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
<div>
|
||||
<v-chip
|
||||
label
|
||||
color="accent custom-transparent"
|
||||
class="ma-1"
|
||||
style="height:100%;"
|
||||
>
|
||||
<v-icon left>
|
||||
{{ $globals.icons.calendar }}
|
||||
</v-icon>
|
||||
Last Made {{ value ? new Date(value).toLocaleDateString($i18n.locale) : "Never" }}
|
||||
</v-chip>
|
||||
<BaseButton @click="madeThisDialog = true">
|
||||
<template #icon> {{ $globals.icons.chefHat }} </template>
|
||||
I Made This
|
||||
</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, ref, toRefs, useContext, } from "@nuxtjs/composition-api";
|
||||
import { whenever } from "@vueuse/core";
|
||||
import { VForm } from "~/types/vuetify";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { RecipeTimelineEventIn } from "~/lib/api/types/recipe";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
recipeSlug: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
const madeThisDialog = ref(false);
|
||||
const userApi = useUserApi();
|
||||
const { $auth } = useContext();
|
||||
const domMadeThisForm = ref<VForm>();
|
||||
const newTimelineEvent = ref<RecipeTimelineEventIn>({
|
||||
// @ts-expect-error - TS doesn't like the $auth global user attribute
|
||||
// eslint-disable-next-line
|
||||
subject: `${$auth.user.fullName} made this`,
|
||||
eventType: "comment",
|
||||
eventMessage: "",
|
||||
timestamp: "",
|
||||
});
|
||||
|
||||
const state = reactive({datePickerMenu: false});
|
||||
|
||||
whenever(
|
||||
() => madeThisDialog.value,
|
||||
() => {
|
||||
// Set timestamp to now
|
||||
newTimelineEvent.value.timestamp = new Date().toISOString().substring(0, 10);
|
||||
}
|
||||
);
|
||||
|
||||
async function createTimelineEvent() {
|
||||
if (!newTimelineEvent.value.timestamp) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actions: Promise<any>[] = []
|
||||
|
||||
// the user only selects the date, so we set the time to noon
|
||||
newTimelineEvent.value.timestamp += "T12:00:00";
|
||||
actions.push(userApi.recipes.createTimelineEvent(props.recipeSlug, newTimelineEvent.value));
|
||||
|
||||
// we also update the recipe's last made value
|
||||
if (!props.value || newTimelineEvent.value.timestamp > props.value) {
|
||||
const payload = {lastMade: newTimelineEvent.value.timestamp};
|
||||
actions.push(userApi.recipes.patchOne(props.recipeSlug, payload));
|
||||
|
||||
// update recipe in parent so the user can see it
|
||||
context.emit("input", newTimelineEvent.value.timestamp);
|
||||
}
|
||||
|
||||
await Promise.allSettled(actions)
|
||||
|
||||
// reset form
|
||||
newTimelineEvent.value.eventMessage = "";
|
||||
madeThisDialog.value = false;
|
||||
domMadeThisForm.value?.reset();
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
domMadeThisForm,
|
||||
madeThisDialog,
|
||||
newTimelineEvent,
|
||||
createTimelineEvent,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue