feat: add filter input
This commit is contained in:
2
src/components.d.ts
vendored
2
src/components.d.ts
vendored
@@ -19,6 +19,8 @@ declare module '@vue/runtime-core' {
|
|||||||
ReloadPrompt: typeof import('./components/ReloadPrompt.vue')['default']
|
ReloadPrompt: typeof import('./components/ReloadPrompt.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
Search: typeof import('./components/Search.vue')['default']
|
||||||
|
SearchFood: typeof import('./components/SearchFood.vue')['default']
|
||||||
StapleTag: typeof import('./components/tags/StapleTag.vue')['default']
|
StapleTag: typeof import('./components/tags/StapleTag.vue')['default']
|
||||||
Switch: typeof import('./components/Switch.vue')['default']
|
Switch: typeof import('./components/Switch.vue')['default']
|
||||||
ToggleMode: typeof import('./components/ToggleMode.vue')['default']
|
ToggleMode: typeof import('./components/ToggleMode.vue')['default']
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type { StuffItem } from '~/data/food'
|
|||||||
import { meat, staple, tools, vegetable } from '~/data/food'
|
import { meat, staple, tools, vegetable } from '~/data/food'
|
||||||
import recipeData from '~/data/recipe.json'
|
import recipeData from '~/data/recipe.json'
|
||||||
import type { Recipe, RecipeItem } from '~/types'
|
import type { Recipe, RecipeItem } from '~/types'
|
||||||
import { useRecipeStore } from '~/stores/recipe'
|
import { useRecipeStore } from '~/store/recipe'
|
||||||
|
|
||||||
import { useInvisibleElement } from '~/composables/helper'
|
import { useInvisibleElement } from '~/composables/helper'
|
||||||
import { useEmojiAnimation } from '~/composables/animation'
|
import { useEmojiAnimation } from '~/composables/animation'
|
||||||
@@ -161,6 +161,8 @@ const randomRecipe = ref<RecipeItem>(generateRandomRecipe())
|
|||||||
|
|
||||||
<!-- <Switch /> -->
|
<!-- <Switch /> -->
|
||||||
<div class="cook-recipes" p="2">
|
<div class="cook-recipes" p="2">
|
||||||
|
<SearchFood />
|
||||||
|
|
||||||
<Transition mode="out-in">
|
<Transition mode="out-in">
|
||||||
<div class="cook-filter-recipes">
|
<div class="cook-filter-recipes">
|
||||||
<span v-if="!curStuff.length && !curTool" text="sm" p="2">
|
<span v-if="!curStuff.length && !curTool" text="sm" p="2">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useAppStore } from '~/stores/app'
|
import { useAppStore } from '~/store/app'
|
||||||
const app = useAppStore()
|
const app = useAppStore()
|
||||||
|
|
||||||
const install = () => {
|
const install = () => {
|
||||||
|
|||||||
33
src/components/SearchFood.vue
Normal file
33
src/components/SearchFood.vue
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { useRecipeStore } from "~/store/recipe";
|
||||||
|
const rStore = useRecipeStore()
|
||||||
|
|
||||||
|
const clearKeyword = () => {
|
||||||
|
rStore.keyword = ''
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div m="auto b-2" max-w="500px">
|
||||||
|
<div relative text-xs>
|
||||||
|
<div v-show="rStore.keyword" cursor="pointer" absolute right-2 inline-flex justify="center" items-center h="full" opacity="70" @click="clearKeyword">
|
||||||
|
<div i-ri-close-line />
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
id="input"
|
||||||
|
v-model="rStore.keyword"
|
||||||
|
placeholder="关键字过滤"
|
||||||
|
aria-label="搜索关键字"
|
||||||
|
type="text"
|
||||||
|
autocomplete="false"
|
||||||
|
p="x4 y2"
|
||||||
|
w="full"
|
||||||
|
text="center"
|
||||||
|
bg="transparent"
|
||||||
|
border="~ rounded gray-200 dark:gray-700"
|
||||||
|
class="focus:(dark:gray-500)"
|
||||||
|
>
|
||||||
|
<label class="hidden" for="input">快速搜索</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { SearchMode } from '~/stores/recipe'
|
import type { SearchMode } from '~/store/recipe'
|
||||||
import { useRecipeStore } from '~/stores/recipe'
|
import { useRecipeStore } from '~/store/recipe'
|
||||||
|
|
||||||
const rStore = useRecipeStore()
|
const rStore = useRecipeStore()
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { storeToRefs } from 'pinia'
|
|||||||
import { useGtm } from '@gtm-support/vue-gtm'
|
import { useGtm } from '@gtm-support/vue-gtm'
|
||||||
import type { Recipe } from '~/types'
|
import type { Recipe } from '~/types'
|
||||||
|
|
||||||
import { useRecipeStore } from '~/stores/recipe'
|
import { useRecipeStore } from '~/store/recipe'
|
||||||
import type { StuffItem } from '~/data/food'
|
import type { StuffItem } from '~/data/food'
|
||||||
|
|
||||||
export function useRecipe(recipe: Ref<Recipe>) {
|
export function useRecipe(recipe: Ref<Recipe>) {
|
||||||
@@ -15,6 +15,12 @@ export function useRecipe(recipe: Ref<Recipe>) {
|
|||||||
|
|
||||||
// 默认严格模式
|
// 默认严格模式
|
||||||
const displayedRecipe = computed(() => {
|
const displayedRecipe = computed(() => {
|
||||||
|
// if keyword exist, return result directly
|
||||||
|
const keyword = rStore.keyword
|
||||||
|
if (keyword) {
|
||||||
|
return recipe.value.filter(item => item.name.includes(keyword))
|
||||||
|
}
|
||||||
|
|
||||||
if (curMode.value === 'strict') {
|
if (curMode.value === 'strict') {
|
||||||
return recipe.value.filter((item) => {
|
return recipe.value.filter((item) => {
|
||||||
const stuffFlag = curStuff.value.every(stuff => item.stuff.includes(stuff))
|
const stuffFlag = curStuff.value.every(stuff => item.stuff.includes(stuff))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { links } from '~/constants';
|
import { links } from '~/constants';
|
||||||
import { useRecipeStore } from '~/stores/recipe'
|
import { useRecipeStore } from '~/store/recipe'
|
||||||
const rStore = useRecipeStore()
|
const rStore = useRecipeStore()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ const namespace = 'cook'
|
|||||||
export type SearchMode = 'survival' | 'loose' | 'strict'
|
export type SearchMode = 'survival' | 'loose' | 'strict'
|
||||||
|
|
||||||
export const useRecipeStore = defineStore('recipe', () => {
|
export const useRecipeStore = defineStore('recipe', () => {
|
||||||
|
/**
|
||||||
|
* 搜索关键字
|
||||||
|
*/
|
||||||
|
const keyword = ref('')
|
||||||
|
|
||||||
// can not exported
|
// can not exported
|
||||||
const curStuff = useStorage(`${namespace}:stuff`, new Set<string>())
|
const curStuff = useStorage(`${namespace}:stuff`, new Set<string>())
|
||||||
// const curTools = ref(new Set<string>())
|
// const curTools = ref(new Set<string>())
|
||||||
@@ -59,6 +64,7 @@ export const useRecipeStore = defineStore('recipe', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
keyword,
|
||||||
curTool,
|
curTool,
|
||||||
curMode,
|
curMode,
|
||||||
selectedStuff,
|
selectedStuff,
|
||||||
@@ -13,6 +13,10 @@ html.dark {
|
|||||||
background: #121212;
|
background: #121212;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
#nprogress {
|
#nprogress {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { isClient } from '@vueuse/core'
|
import { isClient } from '@vueuse/core'
|
||||||
import { useAppStore } from '~/stores/app'
|
import { useAppStore } from '~/store/app'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://web.dev/customize-install/#detect-install
|
* https://web.dev/customize-install/#detect-install
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { describe, it } from 'vitest'
|
import { describe, it } from 'vitest'
|
||||||
// import { createTestingPinia } from '@pinia/testing'
|
// import { createTestingPinia } from '@pinia/testing'
|
||||||
// import ChooseFood from '../src/components/ChooseFood.vue'
|
// import ChooseFood from '../src/components/ChooseFood.vue'
|
||||||
// import { useRecipeStore } from '~/stores/recipe'
|
// import { useRecipeStore } from '~/store/recipe'
|
||||||
|
|
||||||
describe('ChooseFood.vue', () => {
|
describe('ChooseFood.vue', () => {
|
||||||
it('should render', async () => {
|
it('should render', async () => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createPinia, setActivePinia } from 'pinia'
|
|||||||
import { useRecipe } from '~/composables/recipe'
|
import { useRecipe } from '~/composables/recipe'
|
||||||
import type { Recipe } from '~/types'
|
import type { Recipe } from '~/types'
|
||||||
import recipeData from '~/data/recipe.json'
|
import recipeData from '~/data/recipe.json'
|
||||||
import { useRecipeStore } from '~/stores/recipe'
|
import { useRecipeStore } from '~/store/recipe'
|
||||||
|
|
||||||
const recipe = ref<Recipe>(recipeData as Recipe)
|
const recipe = ref<Recipe>(recipeData as Recipe)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user