| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  | <template> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |   <v-timeline-item :class="attrs.class" fill-dot :small="attrs.small" :icon="icon" dot-color="primary"> | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     <template v-if="!useMobileFormat" #opposite> | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |       <v-chip v-if="event.timestamp" label large> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         <v-icon class="mr-1"> | 
					
						
							|  |  |  |           {{ $globals.icons.calendar }} | 
					
						
							|  |  |  |         </v-icon> | 
					
						
							| 
									
										
										
										
											2024-07-08 16:12:20 -05:00
										 |  |  |         {{ new Date(event.timestamp).toLocaleDateString($i18n.locale) }} | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |       </v-chip> | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     </template> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |     <v-card | 
					
						
							|  |  |  |       hover | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       :to="$attrs.selected || !recipe ? undefined : `/g/${groupSlug}/r/${recipe.slug}`" | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |       class="elevation-12" | 
					
						
							| 
									
										
										
										
											2023-10-07 14:23:47 -05:00
										 |  |  |       @click="$emit('selected')" | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |     > | 
					
						
							|  |  |  |       <v-card-title class="background"> | 
					
						
							|  |  |  |         <v-row> | 
					
						
							|  |  |  |           <v-col align-self="center" :cols="useMobileFormat ? 'auto' : '2'" :class="attrs.avatar.class"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <UserAvatar :user-id="event.userId" :size="attrs.avatar.size" /> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |           </v-col> | 
					
						
							|  |  |  |           <v-col v-if="useMobileFormat" align-self="center" class="pr-0"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <v-chip label> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |               <v-icon> {{ $globals.icons.calendar }} </v-icon> | 
					
						
							| 
									
										
										
										
											2024-07-08 16:12:20 -05:00
										 |  |  |               {{ new Date(event.timestamp || "").toLocaleDateString($i18n.locale) }} | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             </v-chip> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |           </v-col> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |           <v-col v-else cols="9" style="margin: auto; text-align: center"> | 
					
						
							|  |  |  |             {{ event.subject }} | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |           </v-col> | 
					
						
							|  |  |  |           <v-spacer /> | 
					
						
							|  |  |  |           <v-col :cols="useMobileFormat ? 'auto' : '1'" class="px-0 pt-0"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <RecipeTimelineContextMenu | 
					
						
							|  |  |  |               v-if="currentUser && currentUser.id == event.userId && event.eventType != 'system'" | 
					
						
							|  |  |  |               :menu-top="false" | 
					
						
							|  |  |  |               :event="event" | 
					
						
							|  |  |  |               :menu-icon="$globals.icons.dotsVertical" | 
					
						
							|  |  |  |               :use-mobile-format="useMobileFormat" | 
					
						
							|  |  |  |               color="transparent" | 
					
						
							|  |  |  |               :elevation="0" | 
					
						
							|  |  |  |               :card-menu="false" | 
					
						
							|  |  |  |               :use-items="{ | 
					
						
							|  |  |  |                 edit: true, | 
					
						
							|  |  |  |                 delete: true, | 
					
						
							|  |  |  |               }" | 
					
						
							|  |  |  |               @update="$emit('update')" | 
					
						
							|  |  |  |               @delete="$emit('delete')" | 
					
						
							|  |  |  |             /> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |           </v-col> | 
					
						
							|  |  |  |         </v-row> | 
					
						
							|  |  |  |       </v-card-title> | 
					
						
							|  |  |  |       <v-card-text v-if="showRecipeCards && recipe" class="background"> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         <v-row :class="useMobileFormat ? 'py-3 mx-0' : 'py-3 mx-0'" style="max-width: 100%"> | 
					
						
							|  |  |  |           <v-col align-self="center" class="pa-0"> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |             <RecipeCardMobile | 
					
						
							|  |  |  |               :vertical="useMobileFormat" | 
					
						
							|  |  |  |               :name="recipe.name" | 
					
						
							|  |  |  |               :slug="recipe.slug" | 
					
						
							|  |  |  |               :description="recipe.description" | 
					
						
							|  |  |  |               :rating="recipe.rating" | 
					
						
							|  |  |  |               :image="recipe.image" | 
					
						
							|  |  |  |               :recipe-id="recipe.id" | 
					
						
							|  |  |  |               :is-flat="true" | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |           </v-col> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         </v-row> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |       </v-card-text> | 
					
						
							|  |  |  |       <v-divider v-if="showRecipeCards && recipe && (useMobileFormat || event.eventMessage)" /> | 
					
						
							|  |  |  |       <v-card-text class="background"> | 
					
						
							|  |  |  |         <v-row> | 
					
						
							|  |  |  |           <v-col> | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             <strong v-if="useMobileFormat">{{ event.subject }}</strong> | 
					
						
							|  |  |  |             <v-img | 
					
						
							|  |  |  |               v-if="eventImageUrl" | 
					
						
							|  |  |  |               :src="eventImageUrl" | 
					
						
							|  |  |  |               min-height="50" | 
					
						
							|  |  |  |               :height="hideImage ? undefined : 'auto'" | 
					
						
							|  |  |  |               :max-height="attrs.image.maxHeight" | 
					
						
							|  |  |  |               contain | 
					
						
							|  |  |  |               :class="attrs.image.class" | 
					
						
							|  |  |  |               @error="hideImage = true" | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |             <div v-if="event.eventMessage" :class="useMobileFormat ? 'text-caption' : ''"> | 
					
						
							|  |  |  |               <SafeMarkdown :source="event.eventMessage" /> | 
					
						
							|  |  |  |             </div> | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  |           </v-col> | 
					
						
							|  |  |  |         </v-row> | 
					
						
							|  |  |  |       </v-card-text> | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     </v-card> | 
					
						
							|  |  |  |   </v-timeline-item> | 
					
						
							|  |  |  | </template> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <script lang="ts"> | 
					
						
							|  |  |  | import RecipeCardMobile from "./RecipeCardMobile.vue"; | 
					
						
							|  |  |  | import RecipeTimelineContextMenu from "./RecipeTimelineContextMenu.vue"; | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  | import { useStaticRoutes } from "~/composables/api"; | 
					
						
							| 
									
										
										
										
											2024-03-12 10:20:48 -05:00
										 |  |  | import { useTimelineEventTypes } from "~/composables/recipes/use-recipe-timeline-events"; | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  | import type { Recipe, RecipeTimelineEventOut } from "~/lib/api/types/recipe"; | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  | import UserAvatar from "~/components/Domain/User/UserAvatar.vue"; | 
					
						
							| 
									
										
										
										
											2023-11-24 10:41:58 +01:00
										 |  |  | import SafeMarkdown from "~/components/global/SafeMarkdown.vue"; | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  | export default defineNuxtComponent({ | 
					
						
							| 
									
										
										
										
											2023-11-24 10:41:58 +01:00
										 |  |  |   components: { RecipeCardMobile, RecipeTimelineContextMenu, UserAvatar, SafeMarkdown }, | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   props: { | 
					
						
							|  |  |  |     event: { | 
					
						
							|  |  |  |       type: Object as () => RecipeTimelineEventOut, | 
					
						
							|  |  |  |       required: true, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     recipe: { | 
					
						
							|  |  |  |       type: Object as () => Recipe, | 
					
						
							|  |  |  |       default: undefined, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     showRecipeCards: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: false, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     }, | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |   }, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |   emits: ["selected", "update", "delete"], | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   setup(props) { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     const { $vuetify, $globals } = useNuxtApp(); | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |     const { recipeTimelineEventImage } = useStaticRoutes(); | 
					
						
							| 
									
										
										
										
											2024-03-12 10:20:48 -05:00
										 |  |  |     const { eventTypeOptions } = useTimelineEventTypes(); | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     const timelineEvents = ref([] as RecipeTimelineEventOut[]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     const { user: currentUser } = useMealieAuth(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-05 19:07:02 -06:00
										 |  |  |     const route = useRoute(); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     const groupSlug = computed(() => (route.params.groupSlug as string) || currentUser?.value?.groupSlug || ""); | 
					
						
							| 
									
										
										
										
											2023-11-05 19:07:02 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     const useMobileFormat = computed(() => { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       return $vuetify.display.smAndDown.value; | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const attrs = computed(() => { | 
					
						
							|  |  |  |       if (useMobileFormat.value) { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |           class: "px-0", | 
					
						
							|  |  |  |           small: false, | 
					
						
							|  |  |  |           avatar: { | 
					
						
							|  |  |  |             size: "30px", | 
					
						
							|  |  |  |             class: "pr-0", | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |           image: { | 
					
						
							|  |  |  |             maxHeight: "250", | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             class: "my-3", | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |           }, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         }; | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |           class: "px-3", | 
					
						
							|  |  |  |           small: false, | 
					
						
							|  |  |  |           avatar: { | 
					
						
							|  |  |  |             size: "42px", | 
					
						
							|  |  |  |             class: "", | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |           image: { | 
					
						
							|  |  |  |             maxHeight: "300", | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |             class: "mb-5", | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |           }, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |         }; | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-12 10:20:48 -05:00
										 |  |  |     const icon = computed(() => { | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       const option = eventTypeOptions.value.find(option => option.value === props.event.eventType); | 
					
						
							| 
									
										
										
										
											2024-03-12 10:20:48 -05:00
										 |  |  |       return option ? option.icon : $globals.icons.informationVariant; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |     const hideImage = ref(false); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     const eventImageUrl = computed<string>(() => { | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |       if (props.event.image !== "has image") { | 
					
						
							|  |  |  |         return ""; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return recipeTimelineEventImage(props.event.recipeId, props.event.id); | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     return { | 
					
						
							|  |  |  |       attrs, | 
					
						
							| 
									
										
										
										
											2023-11-05 19:07:02 -06:00
										 |  |  |       groupSlug, | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |       icon, | 
					
						
							| 
									
										
										
										
											2023-08-06 12:49:30 -05:00
										 |  |  |       eventImageUrl, | 
					
						
							|  |  |  |       hideImage, | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |       timelineEvents, | 
					
						
							|  |  |  |       useMobileFormat, | 
					
						
							| 
									
										
										
										
											2025-06-20 00:09:12 +07:00
										 |  |  |       currentUser, | 
					
						
							| 
									
										
										
										
											2023-04-25 12:46:00 -05:00
										 |  |  |     }; | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | </script> | 
					
						
							| 
									
										
										
										
											2023-08-21 20:41:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | <style> | 
					
						
							|  |  |  | .v-card::after { | 
					
						
							|  |  |  |   display: none; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-08-23 12:30:59 -05:00
										 |  |  | </style> |