| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  | <template> | 
					
						
							|  |  |  |   <div> | 
					
						
							| 
									
										
										
										
											2022-08-10 07:12:45 +02:00
										 |  |  |     <BaseDialog v-model="dialog" :title="$t('recipe-share.share-recipe')" :icon="$globals.icons.link"> | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |       <v-card-text> | 
					
						
							|  |  |  |         <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="expirationDate" | 
					
						
							| 
									
										
										
										
											2022-08-10 07:12:45 +02:00
										 |  |  |               :label="$t('recipe-share.expiration-date')" | 
					
						
							|  |  |  |               :hint="$t('recipe-share.default-30-days')" | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |               persistent-hint | 
					
						
							|  |  |  |               :prepend-icon="$globals.icons.calendar" | 
					
						
							|  |  |  |               v-bind="attrs" | 
					
						
							|  |  |  |               readonly | 
					
						
							|  |  |  |               v-on="on" | 
					
						
							|  |  |  |             ></v-text-field> | 
					
						
							|  |  |  |           </template> | 
					
						
							| 
									
										
										
										
											2022-01-16 03:38:11 +01:00
										 |  |  |           <v-date-picker v-model="expirationDate" no-title @input="datePickerMenu = false"></v-date-picker> | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |         </v-menu> | 
					
						
							|  |  |  |       </v-card-text> | 
					
						
							|  |  |  |       <v-card-actions class="justify-end"> | 
					
						
							|  |  |  |         <BaseButton small @click="createNewToken"> {{ $t("general.new") }}</BaseButton> | 
					
						
							|  |  |  |       </v-card-actions> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       <v-list-item v-for="token in tokens" :key="token.id" @click="shareRecipe(token.id)"> | 
					
						
							|  |  |  |         <v-list-item-avatar color="grey"> | 
					
						
							|  |  |  |           <v-icon dark class="pa-2"> {{ $globals.icons.link }} </v-icon> | 
					
						
							|  |  |  |         </v-list-item-avatar> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-list-item-content> | 
					
						
							| 
									
										
										
										
											2022-08-10 07:12:45 +02:00
										 |  |  |           <v-list-item-title> {{ $t("recipe-share.expires-at") }} </v-list-item-title> | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  | 
 | 
					
						
							|  |  |  |           <v-list-item-subtitle>{{ $d(new Date(token.expiresAt), "long") }}</v-list-item-subtitle> | 
					
						
							|  |  |  |         </v-list-item-content> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-list-item-action> | 
					
						
							|  |  |  |           <v-btn icon @click.stop="deleteToken(token.id)"> | 
					
						
							|  |  |  |             <v-icon color="error lighten-1"> {{ $globals.icons.delete }} </v-icon> | 
					
						
							|  |  |  |           </v-btn> | 
					
						
							|  |  |  |         </v-list-item-action> | 
					
						
							|  |  |  |         <v-list-item-action> | 
					
						
							|  |  |  |           <v-btn icon @click.stop="copyTokenLink(token.id)"> | 
					
						
							|  |  |  |             <v-icon color="info lighten-1"> {{ $globals.icons.contentCopy }} </v-icon> | 
					
						
							|  |  |  |           </v-btn> | 
					
						
							|  |  |  |         </v-list-item-action> | 
					
						
							|  |  |  |       </v-list-item> | 
					
						
							|  |  |  |     </BaseDialog> | 
					
						
							|  |  |  |   </div> | 
					
						
							|  |  |  | </template> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2023-11-05 19:07:02 -06:00
										 |  |  | import { defineComponent, computed, toRefs, reactive, useContext, useRoute } from "@nuxtjs/composition-api"; | 
					
						
							| 
									
										
										
										
											2022-05-25 10:14:24 -08:00
										 |  |  | import { useClipboard, useShare, whenever } from "@vueuse/core"; | 
					
						
							| 
									
										
										
										
											2022-10-22 11:51:07 -08:00
										 |  |  | import { RecipeShareToken } from "~/lib/api/types/recipe"; | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  | import { useUserApi } from "~/composables/api"; | 
					
						
							|  |  |  | import { alert } from "~/composables/use-toast"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default defineComponent({ | 
					
						
							|  |  |  |   props: { | 
					
						
							|  |  |  |     value: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: false, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     recipeId: { | 
					
						
							| 
									
										
										
										
											2022-02-13 12:23:42 -09:00
										 |  |  |       type: String, | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |       required: true, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     name: { | 
					
						
							|  |  |  |       type: String, | 
					
						
							|  |  |  |       required: true, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   setup(props, context) { | 
					
						
							|  |  |  |     // V-Model Support
 | 
					
						
							|  |  |  |     const dialog = computed({ | 
					
						
							|  |  |  |       get: () => { | 
					
						
							|  |  |  |         return props.value; | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       set: (val) => { | 
					
						
							|  |  |  |         context.emit("input", val); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const state = reactive({ | 
					
						
							|  |  |  |       datePickerMenu: false, | 
					
						
							|  |  |  |       expirationDate: "", | 
					
						
							|  |  |  |       tokens: [] as RecipeShareToken[], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     whenever( | 
					
						
							|  |  |  |       () => props.value, | 
					
						
							|  |  |  |       () => { | 
					
						
							|  |  |  |         // Set expiration date to today + 30 Days
 | 
					
						
							|  |  |  |         const today = new Date(); | 
					
						
							|  |  |  |         const expirationDate = new Date(today.getTime() + 30 * 24 * 60 * 60 * 1000); | 
					
						
							|  |  |  |         state.expirationDate = expirationDate.toISOString().substring(0, 10); | 
					
						
							|  |  |  |         refreshTokens(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-05 19:07:02 -06:00
										 |  |  |     const { $auth, i18n } = useContext(); | 
					
						
							|  |  |  |     const route = useRoute(); | 
					
						
							|  |  |  |     const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || ""); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |     // ============================================================
 | 
					
						
							|  |  |  |     // Token Actions
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const userApi = useUserApi(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function createNewToken() { | 
					
						
							|  |  |  |       // Convert expiration date to timestamp
 | 
					
						
							|  |  |  |       const expirationDate = new Date(state.expirationDate); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const { data } = await userApi.recipes.share.createOne({ | 
					
						
							|  |  |  |         recipeId: props.recipeId, | 
					
						
							| 
									
										
										
										
											2022-05-21 21:22:02 +02:00
										 |  |  |         expiresAt: expirationDate.toISOString(), | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (data) { | 
					
						
							|  |  |  |         state.tokens.push(data); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function deleteToken(id: string) { | 
					
						
							|  |  |  |       await userApi.recipes.share.deleteOne(id); | 
					
						
							|  |  |  |       state.tokens = state.tokens.filter((token) => token.id !== id); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function refreshTokens() { | 
					
						
							| 
									
										
										
										
											2022-06-25 14:39:38 -05:00
										 |  |  |       const { data } = await userApi.recipes.share.getAll(1, -1, { recipe_id: props.recipeId }); | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (data) { | 
					
						
							| 
									
										
										
										
											2022-08-28 20:08:33 -08:00
										 |  |  |         // @ts-expect-error - TODO: This routes doesn't have pagination, but the type are mismatched.
 | 
					
						
							|  |  |  |         state.tokens = data ?? []; | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const { share, isSupported: shareIsSupported } = useShare(); | 
					
						
							|  |  |  |     const { copy } = useClipboard(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function getRecipeText() { | 
					
						
							|  |  |  |       return i18n.t("recipe.share-recipe-message", [props.name]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function getTokenLink(token: string) { | 
					
						
							| 
									
										
										
										
											2023-11-05 19:07:02 -06:00
										 |  |  |       return `${window.location.origin}/g/${groupSlug.value}/shared/r/${token}`; | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function copyTokenLink(token: string) { | 
					
						
							|  |  |  |       await copy(getTokenLink(token)); | 
					
						
							| 
									
										
										
										
											2022-08-10 07:12:45 +02:00
										 |  |  |       alert.success(i18n.t("recipe-share.recipe-link-copied-message") as string); | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function shareRecipe(token: string) { | 
					
						
							|  |  |  |       if (shareIsSupported) { | 
					
						
							|  |  |  |         share({ | 
					
						
							|  |  |  |           title: props.name, | 
					
						
							|  |  |  |           url: getTokenLink(token), | 
					
						
							|  |  |  |           text: getRecipeText() as string, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         await copyTokenLink(token); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       ...toRefs(state), | 
					
						
							|  |  |  |       dialog, | 
					
						
							|  |  |  |       createNewToken, | 
					
						
							|  |  |  |       deleteToken, | 
					
						
							|  |  |  |       shareRecipe, | 
					
						
							|  |  |  |       copyTokenLink, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-01-16 03:38:11 +01:00
										 |  |  | </script> |