mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-21 22:13:31 -07:00
Recipe Search Dialog
This commit is contained in:
parent
8d78af6693
commit
cae6e18c58
1 changed files with 83 additions and 97 deletions
|
@ -52,10 +52,6 @@
|
||||||
<div class="mr-auto">
|
<div class="mr-auto">
|
||||||
{{ $t("search.results") }}
|
{{ $t("search.results") }}
|
||||||
</div>
|
</div>
|
||||||
<!-- <router-link
|
|
||||||
:to="advancedSearchUrl"
|
|
||||||
class="text-primary"
|
|
||||||
> {{ $t("search.advanced-search") }} </router-link> -->
|
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
|
|
||||||
<RecipeCardMobile
|
<RecipeCardMobile
|
||||||
|
@ -76,7 +72,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import RecipeCardMobile from "./RecipeCardMobile.vue";
|
import RecipeCardMobile from "./RecipeCardMobile.vue";
|
||||||
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||||
import type { RecipeSummary } from "~/lib/api/types/recipe";
|
import type { RecipeSummary } from "~/lib/api/types/recipe";
|
||||||
|
@ -85,114 +81,104 @@ import { useRecipeSearch } from "~/composables/recipes/use-recipe-search";
|
||||||
import { usePublicExploreApi } from "~/composables/api/api-client";
|
import { usePublicExploreApi } from "~/composables/api/api-client";
|
||||||
|
|
||||||
const SELECTED_EVENT = "selected";
|
const SELECTED_EVENT = "selected";
|
||||||
export default defineNuxtComponent({
|
|
||||||
components: {
|
|
||||||
RecipeCardMobile,
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(_, context) {
|
// Define emits
|
||||||
const $auth = useMealieAuth();
|
const emit = defineEmits<{
|
||||||
const state = reactive({
|
selected: [recipe: RecipeSummary];
|
||||||
loading: false,
|
}>();
|
||||||
selectedIndex: -1,
|
|
||||||
});
|
|
||||||
|
|
||||||
// ===========================================================================
|
const $auth = useMealieAuth();
|
||||||
// Dialog State Management
|
const loading = ref(false);
|
||||||
const dialog = ref(false);
|
const selectedIndex = ref(-1);
|
||||||
|
|
||||||
// Reset or Grab Recipes on Change
|
// ===========================================================================
|
||||||
watch(dialog, (val) => {
|
// Dialog State Management
|
||||||
|
const dialog = ref(false);
|
||||||
|
|
||||||
|
// Reset or Grab Recipes on Change
|
||||||
|
watch(dialog, (val) => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
search.query.value = "";
|
search.query.value = "";
|
||||||
state.selectedIndex = -1;
|
selectedIndex.value = -1;
|
||||||
search.data.value = [];
|
search.data.value = [];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Event Handlers
|
// Event Handlers
|
||||||
|
|
||||||
function selectRecipe() {
|
function selectRecipe() {
|
||||||
const recipeCards = document.getElementsByClassName("arrow-nav");
|
const recipeCards = document.getElementsByClassName("arrow-nav");
|
||||||
if (recipeCards) {
|
if (recipeCards) {
|
||||||
if (state.selectedIndex < 0) {
|
if (selectedIndex.value < 0) {
|
||||||
state.selectedIndex = -1;
|
selectedIndex.value = -1;
|
||||||
document.getElementById("arrow-search")?.focus();
|
document.getElementById("arrow-search")?.focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.selectedIndex >= recipeCards.length) {
|
if (selectedIndex.value >= recipeCards.length) {
|
||||||
state.selectedIndex = recipeCards.length - 1;
|
selectedIndex.value = recipeCards.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
(recipeCards[state.selectedIndex] as HTMLElement).focus();
|
(recipeCards[selectedIndex.value] as HTMLElement).focus();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onUpDown(e: KeyboardEvent) {
|
function onUpDown(e: KeyboardEvent) {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
console.log(document.activeElement);
|
console.log(document.activeElement);
|
||||||
// (document.activeElement as HTMLElement).click();
|
// (document.activeElement as HTMLElement).click();
|
||||||
}
|
}
|
||||||
else if (e.key === "ArrowUp") {
|
else if (e.key === "ArrowUp") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
state.selectedIndex--;
|
selectedIndex.value--;
|
||||||
}
|
}
|
||||||
else if (e.key === "ArrowDown") {
|
else if (e.key === "ArrowDown") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
state.selectedIndex++;
|
selectedIndex.value++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectRecipe();
|
selectRecipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(dialog, (val) => {
|
watch(dialog, (val) => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
document.removeEventListener("keyup", onUpDown);
|
document.removeEventListener("keyup", onUpDown);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
document.addEventListener("keyup", onUpDown);
|
document.addEventListener("keyup", onUpDown);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || "");
|
const route = useRoute();
|
||||||
const route = useRoute();
|
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || "");
|
||||||
const advancedSearchUrl = computed(() => `/g/${groupSlug.value}`);
|
watch(route, close);
|
||||||
watch(route, close);
|
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
dialog.value = true;
|
dialog.value = true;
|
||||||
}
|
}
|
||||||
function close() {
|
function close() {
|
||||||
dialog.value = false;
|
dialog.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Basic Search
|
// Basic Search
|
||||||
const { isOwnGroup } = useLoggedInState();
|
const { isOwnGroup } = useLoggedInState();
|
||||||
const api = isOwnGroup.value ? useUserApi() : usePublicExploreApi(groupSlug.value).explore;
|
const api = isOwnGroup.value ? useUserApi() : usePublicExploreApi(groupSlug.value).explore;
|
||||||
const search = useRecipeSearch(api);
|
const search = useRecipeSearch(api);
|
||||||
|
|
||||||
// Select Handler
|
// Select Handler
|
||||||
|
function handleSelect(recipe: RecipeSummary) {
|
||||||
function handleSelect(recipe: RecipeSummary) {
|
|
||||||
close();
|
close();
|
||||||
context.emit(SELECTED_EVENT, recipe);
|
emit(SELECTED_EVENT, recipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
// Expose functions to parent components
|
||||||
...toRefs(state),
|
defineExpose({
|
||||||
advancedSearchUrl,
|
|
||||||
dialog,
|
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
handleSelect,
|
|
||||||
search,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue