bottom-bar experiment

This commit is contained in:
hay-kot 2021-04-02 11:32:15 -08:00
commit 087de0739c
8 changed files with 180 additions and 67 deletions

View file

@ -1,35 +1,6 @@
<template> <template>
<v-app> <v-app>
<v-app-bar clipped-left dense app color="primary" dark class="d-print-none"> <TheAppBar />
<router-link v-if="!(isMobile && search)" to="/">
<v-btn icon>
<v-icon size="40"> mdi-silverware-variant </v-icon>
</v-btn>
</router-link>
<div v-if="!isMobile" btn class="pl-2">
<v-toolbar-title style="cursor: pointer" @click="$router.push('/')"
>Mealie
</v-toolbar-title>
</div>
<v-spacer></v-spacer>
<v-expand-x-transition>
<SearchBar
ref="mainSearchBar"
v-if="search"
:show-results="true"
@selected="navigateFromSearch"
:max-width="isMobile ? '100%' : '450px'"
/>
</v-expand-x-transition>
<v-btn icon @click="search = !search">
<v-icon>mdi-magnify</v-icon>
</v-btn>
<SiteMenu />
<LanguageMenu />
</v-app-bar>
<v-main> <v-main>
<v-banner v-if="demo" sticky <v-banner v-if="demo" sticky
><div class="text-center"> ><div class="text-center">
@ -47,10 +18,8 @@
</template> </template>
<script> <script>
import SiteMenu from "@/components/UI/SiteMenu"; import TheAppBar from "@/components/UI/TheAppBar";
import SearchBar from "@/components/UI/Search/SearchBar";
import AddRecipeFab from "@/components/UI/AddRecipeFab"; import AddRecipeFab from "@/components/UI/AddRecipeFab";
import LanguageMenu from "@/components/UI/LanguageMenu";
import Vuetify from "./plugins/vuetify"; import Vuetify from "./plugins/vuetify";
import { user } from "@/mixins/user"; import { user } from "@/mixins/user";
@ -58,23 +27,13 @@ export default {
name: "App", name: "App",
components: { components: {
SiteMenu, TheAppBar,
AddRecipeFab, AddRecipeFab,
SearchBar,
LanguageMenu,
}, },
mixins: [user], mixins: [user],
watch: {
$route() {
this.search = false;
},
},
computed: { computed: {
isMobile() {
return this.$vuetify.breakpoint.name === "xs";
},
demo() { demo() {
const appInfo = this.$store.getters.getAppInfo; const appInfo = this.$store.getters.getAppInfo;
return appInfo.demoStatus; return appInfo.demoStatus;
@ -102,9 +61,6 @@ export default {
this.$store.dispatch("requestAppInfo"); this.$store.dispatch("requestAppInfo");
}, },
data: () => ({
search: false,
}),
methods: { methods: {
// For Later! // For Later!
@ -126,9 +82,6 @@ export default {
this.darkModeSystemCheck(); this.darkModeSystemCheck();
}); });
}, },
navigateFromSearch(slug) {
this.$router.push(`/recipe/${slug}`);
},
}, },
}; };
</script> </script>

View file

@ -5,27 +5,27 @@ import { store } from "@/store";
const prefix = baseURL + "categories"; const prefix = baseURL + "categories";
const categoryURLs = { const categoryURLs = {
get_all: `${prefix}`, getAll: `${prefix}`,
get_category: category => `${prefix}/${category}`, getCategory: category => `${prefix}/${category}`,
delete_category: category => `${prefix}/${category}`, deleteCategory: category => `${prefix}/${category}`,
}; };
export const categoryAPI = { export const categoryAPI = {
async getAll() { async getAll() {
let response = await apiReq.get(categoryURLs.get_all); let response = await apiReq.get(categoryURLs.getAll);
return response.data; return response.data;
}, },
async create(name) { async create(name) {
let response = await apiReq.post(categoryURLs.get_all, { name: name }); let response = await apiReq.post(categoryURLs.getAll, { name: name });
store.dispatch("requestCategories"); store.dispatch("requestCategories");
return response.data; return response.data;
}, },
async getRecipesInCategory(category) { async getRecipesInCategory(category) {
let response = await apiReq.get(categoryURLs.get_category(category)); let response = await apiReq.get(categoryURLs.getCategory(category));
return response.data; return response.data;
}, },
async delete(category) { async delete(category) {
let response = await apiReq.delete(categoryURLs.delete_category(category)); let response = await apiReq.delete(categoryURLs.deleteCategory(category));
store.dispatch("requestCategories"); store.dispatch("requestCategories");
return response.data; return response.data;
}, },

View file

@ -56,9 +56,7 @@ export const recipeAPI = {
const fd = new FormData(); const fd = new FormData();
fd.append("image", fileObject); fd.append("image", fileObject);
fd.append("extension", fileObject.name.split(".").pop()); fd.append("extension", fileObject.name.split(".").pop());
let response = apiReq.put(recipeURLs.updateImage(recipeSlug), fd); let response = apiReq.put(recipeURLs.updateImage(recipeSlug), fd);
return response; return response;
}, },

View file

@ -1,5 +1,10 @@
<template> <template>
<v-card hover :to="`/recipe/${slug}`" max-height="125"> <v-card
hover
:to="`/recipe/${slug}`"
max-height="125"
@click="$emit('selected')"
>
<v-list-item> <v-list-item>
<v-list-item-avatar rounded size="125" class="mt-0 ml-n4"> <v-list-item-avatar rounded size="125" class="mt-0 ml-n4">
<v-img :src="getImage(image)"> </v-img> <v-img :src="getImage(image)"> </v-img>

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="text-center "> <div class="text-center ">
<v-dialog v-model="dialog" class="search-dialog" width="600px" height="0"> <v-dialog v-model="dialog" width="600px" height="0" :fullscreen="isMobile">
<v-card> <v-card>
<v-app-bar dark color="primary"> <v-app-bar dark color="primary">
<v-toolbar-title class="headline">Search a Recipe</v-toolbar-title> <v-toolbar-title class="headline">Search a Recipe</v-toolbar-title>
@ -9,13 +9,27 @@
<SearchBar <SearchBar
@results="updateResults" @results="updateResults"
@selected="emitSelect" @selected="emitSelect"
:show-results="true" :show-results="!isMobile"
max-width="550px" max-width="550px"
:dense="false" :dense="false"
:nav-on-click="false" :nav-on-click="false"
:reset-search="dialog" :reset-search="dialog"
:solo="false" :solo="false"
/> />
<div v-if="isMobile">
<div v-for="recipe in searchResults.slice(0, 7)" :key="recipe.name">
<MobileRecipeCard
class="ma-1 px-0"
:name="recipe.item.name"
:description="recipe.item.description"
:slug="recipe.item.slug"
:rating="recipe.item.rating"
:image="recipe.item.image"
:route="true"
@selected="dialog = false"
/>
</div>
</div>
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-dialog> </v-dialog>
@ -24,16 +38,32 @@
<script> <script>
import SearchBar from "./SearchBar"; import SearchBar from "./SearchBar";
import MobileRecipeCard from "@/components/Recipe/MobileRecipeCard";
export default { export default {
components: { components: {
SearchBar, SearchBar,
MobileRecipeCard,
}, },
data() { data() {
return { return {
searchResults: null, searchResults: [],
dialog: false, dialog: false,
}; };
}, },
computed: {
isMobile() {
return this.$vuetify.breakpoint.name === "xs";
},
},
watch: {
"$route.hash"(newHash, oldHash) {
if (newHash === "#mobile-search") {
this.dialog = true;
} else if (oldHash === "#mobile-search") {
this.dialog = false;
}
},
},
methods: { methods: {
updateResults(results) { updateResults(results) {
this.searchResults = results; this.searchResults = results;
@ -44,15 +74,22 @@ export default {
}, },
open() { open() {
this.dialog = true; this.dialog = true;
this.$router.push("#mobile-search");
},
toggleDialog(open) {
if (open) {
this.$router.push("#mobile-search");
} else {
this.$router.back(); // 😎 back button click
}
}, },
}, },
}; };
</script> </script>
<style scope> <style scope>
.search-dialog { .mobile-dialog {
margin-top: 10%;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: flex-start;
} }
</style> </style>

View file

@ -0,0 +1,113 @@
<template>
<div>
<v-app-bar
v-if="!isMobile"
clipped-left
dense
app
color="primary"
dark
class="d-print-none"
>
<router-link v-if="!(isMobile && search)" to="/">
<v-btn icon>
<v-icon size="40"> mdi-silverware-variant </v-icon>
</v-btn>
</router-link>
<div v-if="!isMobile" btn class="pl-2">
<v-toolbar-title style="cursor: pointer" @click="$router.push('/')"
>Mealie
</v-toolbar-title>
</div>
<v-spacer></v-spacer>
<v-expand-x-transition>
<SearchBar
ref="mainSearchBar"
v-if="search"
:show-results="true"
@selected="navigateFromSearch"
:max-width="isMobile ? '100%' : '450px'"
/>
</v-expand-x-transition>
<v-btn icon @click="search = !search">
<v-icon>mdi-magnify</v-icon>
</v-btn>
<SiteMenu />
</v-app-bar>
<v-app-bar
v-else
bottom
clipped-left
dense
app
color="primary"
dark
class="d-print-none"
>
<router-link to="/">
<v-btn icon>
<v-icon size="40"> mdi-silverware-variant </v-icon>
</v-btn>
</router-link>
<div v-if="!isMobile" btn class="pl-2">
<v-toolbar-title style="cursor: pointer" @click="$router.push('/')"
>Mealie
</v-toolbar-title>
</div>
<v-spacer></v-spacer>
<v-expand-x-transition>
<SearchDialog ref="mainSearchDialog" />
</v-expand-x-transition>
<v-btn icon @click="$refs.mainSearchDialog.open()">
<v-icon>mdi-magnify</v-icon>
</v-btn>
<SiteMenu />
</v-app-bar>
</div>
</template>
<script>
import SiteMenu from "@/components/UI/SiteMenu";
import SearchBar from "@/components/UI/Search/SearchBar";
import SearchDialog from "@/components/UI/Search/SearchDialog";
import { user } from "@/mixins/user";
export default {
name: "AppBar",
mixins: [user],
components: {
SiteMenu,
SearchBar,
SearchDialog,
},
data() {
return {
search: false,
};
},
watch: {
$route() {
this.search = false;
},
},
computed: {
isMobile() {
return this.$vuetify.breakpoint.name === "xs";
},
},
methods: {
navigateFromSearch(slug) {
this.$router.push(`/recipe/${slug}`);
},
},
};
</script>
<style lang="scss" scoped>
</style>

View file

@ -0,0 +1,7 @@
export const utilMixins = {
commputed: {
isMobile() {
return this.$vuetify.breakpoint.name === "xs";
},
},
};

View file

@ -70,7 +70,7 @@ const actions = {
async refreshToken({ commit, getters }) { async refreshToken({ commit, getters }) {
if (!getters.getIsLoggedIn) { if (!getters.getIsLoggedIn) {
commit("setIsLoggedIn", false); // This is to be here... for some reasons? ¯\_(ツ)_/¯ commit("setIsLoggedIn", false); // This has to be here... for some reasons? ¯\_(ツ)_/¯
console.log("Not Logged In"); console.log("Not Logged In");
return; return;
} }