mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 18:23:18 -04:00 
			
		
		
		
	* add groupSlug to most routes * fixed more routing issues * fixed jank and incorrect routes * remove public explore links * remove unused groupSlug and explore routes * nuked explore pages * fixed public toolstore bug * fixed various routes missing group slug * restored public app header menu * fix janky login redirect * 404 recipe API call returns to login * removed unused explore layout * force redirect when using the wrong group slug * fixed dead admin links * removed unused middleware from earlier attempt * 🧹 * improve cookbooks sidebar fixed sidebar link not working fixed sidebar link target hide cookbooks header when there are none * added group slug to user * fix $auth typehints * vastly simplified groupSlug logic * allow logged-in users to view other groups * fixed some edgecases that bypassed isOwnGroup * fixed static home ref * 🧹 * fixed redirect logic * lint warning * removed group slug from group and user pages refactored all components to use route groupSlug or user group slug moved some group pages to recipe pages * fixed some bad types * 🧹 * moved groupSlug routes under /g/groupSlug * move /recipe/ to /r/ * fix backend url generation and metadata injection * moved shopping lists to root/other route fixes * changed shared from /recipes/ to /r/ * fixed 404 redirect not awaiting * removed unused import * fix doc links * fix public recipe setting not affecting public API * fixed backend tests * fix nuxt-generate command --------- Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
		
			
				
	
	
		
			163 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { computed, ComputedRef, ref, Ref, useContext } from "@nuxtjs/composition-api";
 | |
| import { UserOut } from "~/lib/api/types/user";
 | |
| 
 | |
| export enum PageMode {
 | |
|   EDIT = "EDIT",
 | |
|   VIEW = "VIEW",
 | |
|   COOK = "COOK",
 | |
| }
 | |
| 
 | |
| export enum EditorMode {
 | |
|   JSON = "JSON",
 | |
|   FORM = "FORM",
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * PageState encapsulates the state of the recipe page the can be shared across components.
 | |
|  * It allows and facilitates the complex state management of the recipe page where many components
 | |
|  * need to share and communicate with each other and guarantee consistency.
 | |
|  *
 | |
|  * **Page Modes**
 | |
|  *
 | |
|  * are ComputedRefs so we can use a readonly reactive copy of the state of the page.
 | |
|  */
 | |
| interface PageState {
 | |
|   slug: Ref<string>;
 | |
|   imageKey: Ref<number>;
 | |
| 
 | |
|   pageMode: ComputedRef<PageMode>;
 | |
|   editMode: ComputedRef<EditorMode>;
 | |
| 
 | |
|   /**
 | |
|    * true is the page is in edit mode and the edit mode is in form mode.
 | |
|    */
 | |
|   isEditForm: ComputedRef<boolean>;
 | |
|   /**
 | |
|    * true is the page is in edit mode and the edit mode is in json mode.
 | |
|    */
 | |
|   isEditJSON: ComputedRef<boolean>;
 | |
|   /**
 | |
|    * true is the page is in view mode.
 | |
|    */
 | |
|   isEditMode: ComputedRef<boolean>;
 | |
|   /**
 | |
|    * true is the page is in cook mode.
 | |
|    */
 | |
|   isCookMode: ComputedRef<boolean>;
 | |
| 
 | |
|   setMode: (v: PageMode) => void;
 | |
|   setEditMode: (v: EditorMode) => void;
 | |
|   toggleEditMode: () => void;
 | |
|   toggleCookMode: () => void;
 | |
| }
 | |
| 
 | |
| type PageRefs = ReturnType<typeof pageRefs>;
 | |
| 
 | |
| const memo: Record<string, PageRefs> = {};
 | |
| 
 | |
| function pageRefs(slug: string) {
 | |
|   return {
 | |
|     slugRef: ref(slug),
 | |
|     pageModeRef: ref(PageMode.VIEW),
 | |
|     editModeRef: ref(EditorMode.FORM),
 | |
|     imageKey: ref(1),
 | |
|   };
 | |
| }
 | |
| 
 | |
| function pageState({ slugRef, pageModeRef, editModeRef, imageKey }: PageRefs): PageState {
 | |
|   const toggleEditMode = () => {
 | |
|     if (editModeRef.value === EditorMode.FORM) {
 | |
|       editModeRef.value = EditorMode.JSON;
 | |
|       return;
 | |
|     }
 | |
|     editModeRef.value = EditorMode.FORM;
 | |
|   };
 | |
| 
 | |
|   const toggleCookMode = () => {
 | |
|     if (pageModeRef.value === PageMode.COOK) {
 | |
|       pageModeRef.value = PageMode.VIEW;
 | |
|       return;
 | |
|     }
 | |
|     pageModeRef.value = PageMode.COOK;
 | |
|   };
 | |
| 
 | |
|   const setEditMode = (v: EditorMode) => {
 | |
|     editModeRef.value = v;
 | |
|   };
 | |
| 
 | |
|   const setMode = (toMode: PageMode) => {
 | |
|     const fromMode = pageModeRef.value;
 | |
| 
 | |
|     if (fromMode === PageMode.EDIT && toMode === PageMode.VIEW) {
 | |
|       setEditMode(EditorMode.FORM);
 | |
|     }
 | |
| 
 | |
|     pageModeRef.value = toMode;
 | |
|   };
 | |
| 
 | |
|   return {
 | |
|     slug: slugRef,
 | |
|     pageMode: computed(() => pageModeRef.value),
 | |
|     editMode: computed(() => editModeRef.value),
 | |
|     imageKey,
 | |
| 
 | |
|     toggleEditMode,
 | |
|     setMode,
 | |
|     setEditMode,
 | |
|     toggleCookMode,
 | |
| 
 | |
|     isEditForm: computed(() => {
 | |
|       return pageModeRef.value === PageMode.EDIT && editModeRef.value === EditorMode.FORM;
 | |
|     }),
 | |
|     isEditJSON: computed(() => {
 | |
|       return pageModeRef.value === PageMode.EDIT && editModeRef.value === EditorMode.JSON;
 | |
|     }),
 | |
|     isEditMode: computed(() => {
 | |
|       return pageModeRef.value === PageMode.EDIT;
 | |
|     }),
 | |
|     isCookMode: computed(() => {
 | |
|       return pageModeRef.value === PageMode.COOK;
 | |
|     }),
 | |
|   };
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * usePageState provides a common way to interact with shared state across the
 | |
|  * RecipePage component.
 | |
|  */
 | |
| export function usePageState(slug: string): PageState {
 | |
|   if (!memo[slug]) {
 | |
|     memo[slug] = pageRefs(slug);
 | |
|   }
 | |
| 
 | |
|   return pageState(memo[slug]);
 | |
| }
 | |
| 
 | |
| export function clearPageState(slug: string) {
 | |
|   delete memo[slug];
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * usePageUser provides a wrapper around $auth that provides a type-safe way to
 | |
|  * access the UserOut type from the context. If no user is logged in then an empty
 | |
|  * object with all properties set to their zero value is returned.
 | |
|  */
 | |
| export function usePageUser(): { user: UserOut } {
 | |
|   const { $auth } = useContext();
 | |
| 
 | |
|   if (!$auth.user) {
 | |
|     return {
 | |
|       user: {
 | |
|         id: "",
 | |
|         group: "",
 | |
|         groupId: "",
 | |
|         groupSlug: "",
 | |
|         cacheKey: "",
 | |
|         email: "",
 | |
|       },
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   return { user: $auth.user };
 | |
| }
 |