refactor: use nuxt compatiable 4 folder
This commit is contained in:
19
app/composables/store/app.ts
Normal file
19
app/composables/store/app.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { acceptHMRUpdate, defineStore } from 'pinia'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { ref } from 'vue'
|
||||
import { defaultSettings } from '../../utils/settings'
|
||||
import { namespace } from '../../constants'
|
||||
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
const deferredPrompt = ref<Event | any>()
|
||||
const settings = useStorage(`${namespace}:settings`, defaultSettings)
|
||||
|
||||
return {
|
||||
deferredPrompt,
|
||||
|
||||
settings,
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot)
|
||||
import.meta.hot.accept(acceptHMRUpdate(useAppStore, import.meta.hot))
|
||||
10
app/composables/store/history.ts
Normal file
10
app/composables/store/history.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { namespace } from '~/constants'
|
||||
import type { RecipeItem } from '~/types'
|
||||
|
||||
export interface RecipeHistoryItem {
|
||||
recipe: RecipeItem
|
||||
time: number
|
||||
}
|
||||
|
||||
export const recipeHistories = useStorage<RecipeHistoryItem[]>(`${namespace}:history`, [])
|
||||
3
app/composables/store/index.ts
Normal file
3
app/composables/store/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './app'
|
||||
export * from './recipe'
|
||||
export * from './user'
|
||||
185
app/composables/store/recipe.ts
Normal file
185
app/composables/store/recipe.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
import { acceptHMRUpdate, defineStore } from 'pinia'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
import { useGtm } from '@gtm-support/vue-gtm'
|
||||
import { db } from '../../utils/db'
|
||||
import { useAppStore } from './app'
|
||||
import type { RecipeItem, StuffItem } from '~/types'
|
||||
|
||||
const namespace = 'cook'
|
||||
|
||||
/**
|
||||
* survival: 生存模式
|
||||
* strict: 严格
|
||||
* loose: 模糊
|
||||
*/
|
||||
export type SearchMode = 'survival' | 'loose' | 'strict'
|
||||
|
||||
export const useRecipeStore = defineStore('recipe', () => {
|
||||
const gtm = useGtm()
|
||||
const { settings } = useAppStore()
|
||||
|
||||
/**
|
||||
* 搜索关键字
|
||||
*/
|
||||
const keyword = ref('')
|
||||
|
||||
// can not exported
|
||||
const curStuff = settings.keepLocalData ? useStorage(`${namespace}:stuff`, new Set<string>()) : ref(new Set<string>())
|
||||
// const curTools = ref(new Set<string>())
|
||||
const curTool = settings.keepLocalData ? useStorage(`${namespace}:tool`, '') : ref('')
|
||||
const curMode = settings.keepLocalData ? useStorage<SearchMode>(`${namespace}:mode`, 'loose') : ref<SearchMode>('loose')
|
||||
|
||||
const selectedStuff = computed(() => Array.from(curStuff.value))
|
||||
// const selectedTools = computed(() => Array.from(curTools.value))
|
||||
// const selectedTools = ref('')
|
||||
|
||||
function toggleStuff(name: string) {
|
||||
if (!curStuff.value)
|
||||
return
|
||||
if (curStuff.value.has(name))
|
||||
curStuff.value.delete(name)
|
||||
else
|
||||
curStuff.value.add(name)
|
||||
}
|
||||
|
||||
function toggleTools(name: string) {
|
||||
if (curTool.value === name)
|
||||
curTool.value = ''
|
||||
else
|
||||
curTool.value = name
|
||||
// if (curTools.value.has(name))
|
||||
// curTools.value.delete(name)
|
||||
// else
|
||||
// curTools.value.add(name)
|
||||
}
|
||||
|
||||
function setMode(mode: SearchMode) {
|
||||
curMode.value = mode
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
function reset() {
|
||||
curStuff.value.clear()
|
||||
// curTools.value.clear()
|
||||
curTool.value = ''
|
||||
}
|
||||
|
||||
function addStuff(name: string) {
|
||||
curStuff.value.add(name)
|
||||
}
|
||||
|
||||
const isSearching = ref(false)
|
||||
/**
|
||||
* 搜索菜谱
|
||||
*/
|
||||
async function searchRecipes() {
|
||||
isSearching.value = true
|
||||
let result: RecipeItem[] = []
|
||||
|
||||
if (curMode.value === 'strict') {
|
||||
result = await db.recipes.filter((item) => {
|
||||
const stuffFlag = selectedStuff.value.every(stuff => item.stuff.includes(stuff))
|
||||
const toolFlag = item.tools.includes(curTool.value)
|
||||
return curTool.value ? (stuffFlag && toolFlag) : stuffFlag
|
||||
}).toArray()
|
||||
}
|
||||
else if (curMode.value === 'loose') {
|
||||
result = await db.recipes.filter((item) => {
|
||||
const stuffFlag = selectedStuff.value.some(stuff => item.stuff.includes(stuff))
|
||||
const toolFlag = Boolean(item.tools?.includes(curTool.value))
|
||||
|
||||
// 同时存在 厨具和材料,则同时判断
|
||||
if (curTool.value && selectedStuff.value.length) {
|
||||
return stuffFlag && toolFlag
|
||||
}
|
||||
else {
|
||||
if (selectedStuff.value.length)
|
||||
return stuffFlag
|
||||
else if (curTool.value)
|
||||
return toolFlag
|
||||
|
||||
return false
|
||||
}
|
||||
}).toArray()
|
||||
}
|
||||
// survival
|
||||
else {
|
||||
result = await db.recipes.filter((item) => {
|
||||
const stuffFlag = item.stuff.every(stuff => selectedStuff.value.includes(stuff))
|
||||
const toolFlag = item.tools?.includes(curTool.value)
|
||||
return Boolean(curTool.value ? (stuffFlag && toolFlag) : stuffFlag)
|
||||
}).toArray()
|
||||
}
|
||||
|
||||
if (keyword.value)
|
||||
result = result.filter(item => item.name.includes(keyword.value))
|
||||
|
||||
isSearching.value = false
|
||||
return result
|
||||
}
|
||||
|
||||
// 默认严格模式
|
||||
const displayedRecipe = ref<RecipeItem[]>([])
|
||||
// fix curStuff watch
|
||||
watch(() => [keyword.value, selectedStuff.value, curTool.value, curMode.value], async () => {
|
||||
displayedRecipe.value = [...(await searchRecipes())]
|
||||
})
|
||||
|
||||
/**
|
||||
* toggle tool
|
||||
* @param item
|
||||
*/
|
||||
const clickTool = (item: StuffItem) => {
|
||||
const value = item.name
|
||||
toggleTools(value)
|
||||
|
||||
gtm?.trackEvent({
|
||||
event: 'click',
|
||||
category: `tool_${value}`,
|
||||
action: 'click_tool',
|
||||
label: '工具',
|
||||
})
|
||||
gtm?.trackEvent({
|
||||
event: 'click_tool',
|
||||
action: item.name,
|
||||
})
|
||||
}
|
||||
|
||||
const recipesLength = ref(0)
|
||||
onMounted(async () => {
|
||||
db.recipes.count().then((count) => {
|
||||
recipesLength.value = count
|
||||
})
|
||||
|
||||
displayedRecipe.value = await searchRecipes()
|
||||
})
|
||||
|
||||
return {
|
||||
recipesLength,
|
||||
|
||||
keyword,
|
||||
curTool,
|
||||
curMode,
|
||||
selectedStuff,
|
||||
|
||||
isSearching,
|
||||
|
||||
clearKeyWord: () => { keyword.value = '' },
|
||||
toggleStuff,
|
||||
toggleTools,
|
||||
reset,
|
||||
setMode,
|
||||
|
||||
addStuff,
|
||||
|
||||
// useRecipe
|
||||
displayedRecipe,
|
||||
clickTool,
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot)
|
||||
import.meta.hot.accept(acceptHMRUpdate(useRecipeStore, import.meta.hot))
|
||||
34
app/composables/store/user.ts
Normal file
34
app/composables/store/user.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { acceptHMRUpdate, defineStore } from 'pinia'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
/**
|
||||
* Current name of the user.
|
||||
*/
|
||||
const savedName = ref('')
|
||||
const previousNames = ref(new Set<string>())
|
||||
|
||||
const usedNames = computed(() => Array.from(previousNames.value))
|
||||
const otherNames = computed(() => usedNames.value.filter(name => name !== savedName.value))
|
||||
|
||||
/**
|
||||
* Changes the current name of the user and saves the one that was used
|
||||
* before.
|
||||
*
|
||||
* @param name - new name to set
|
||||
*/
|
||||
function setNewName(name: string) {
|
||||
if (savedName.value)
|
||||
previousNames.value.add(savedName.value)
|
||||
|
||||
savedName.value = name
|
||||
}
|
||||
|
||||
return {
|
||||
setNewName,
|
||||
otherNames,
|
||||
savedName,
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot)
|
||||
import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot))
|
||||
Reference in New Issue
Block a user