improved code quality of start page scrollers

This commit is contained in:
vabene1111
2024-12-19 21:16:15 +01:00
parent 1c9d19fc76
commit 3e3780028b
37 changed files with 200 additions and 447 deletions

View File

@@ -1,71 +1,159 @@
<template>
<v-row justify="space-between">
<v-col>
<h4><i v-if="icon != 'undefined'" :class="icon + ' fa-fw'"></i> {{ title }}</h4>
</v-col>
</v-row>
<template v-if="loading || recipes.length > 0">
<v-row justify="space-between">
<v-col>
<h4><i :class="icon + ' fa-fw'"></i> {{ title }}</h4>
</v-col>
</v-row>
<v-row class="mt-0" v-if="recipeWindows.length > 0">
<v-col>
<v-window show-arrows>
<v-window-item v-for="w in recipeWindows" class="pt-1 pb-1">
<v-row>
<v-col v-for="r in w" :key="r.id">
<recipe-card :recipe="r" :show_description="true" :show_keywords="true" style="height: 20vh"></recipe-card>
</v-col>
</v-row>
</v-window-item>
</v-window>
</v-col>
</v-row>
<v-row v-if="recipeWindows.length == 0 && skeletons > 0">
<v-col>
<v-window>
<v-window-item>
<v-row>
<v-col v-for="n in skeletons">
<v-skeleton-loader :elevation="3" type="card"></v-skeleton-loader>
</v-col>
</v-row>
</v-window-item>
</v-window>
</v-col>
</v-row>
<v-row class="mt-0" v-if="recipeWindows.length > 0">
<v-col>
<v-window show-arrows>
<v-window-item v-for="w in recipeWindows" class="pt-1 pb-1">
<v-row>
<v-col v-for="r in w" :key="r.id">
<recipe-card :recipe="r" :show_description="true" :show_keywords="true" style="height: 20vh"></recipe-card>
</v-col>
</v-row>
</v-window-item>
</v-window>
</v-col>
</v-row>
<v-row v-if="skeletons > 0 && loading">
<v-col>
<v-window>
<v-window-item>
<v-row>
<v-col v-for="n in skeletons">
<v-skeleton-loader :elevation="3" type="card"></v-skeleton-loader>
</v-col>
</v-row>
</v-window-item>
</v-window>
</v-col>
</v-row>
</template>
</template>
<script lang="ts" setup>
import {computed, PropType, toRefs} from 'vue'
import {computed, onMounted, PropType, ref, toRefs} from 'vue'
import RecipeCard from "@/components/display/RecipeCard.vue";
import {DisplayBreakpoint, useDisplay} from "vuetify";
import {Recipe, RecipeOverview} from "@/openapi";
import {ApiApi, ApiRecipeListRequest, Keyword, Recipe, RecipeOverview} from "@/openapi";
import {homePageCols} from "@/utils/breakpoint_utils";
import {useI18n} from "vue-i18n";
//TODO mode ideas "last year/month/cooked long ago"
const props = defineProps(
{
title: {type: String as PropType<undefined | String>, required: true},
icon: {type: String, required: false},
mode: {type: String as PropType<'recent' | 'new' | 'keyword' | 'rating'>, required: true},
skeletons: {type: Number, default: 0},
recipes: {
type: Array as PropType<Recipe[] | RecipeOverview[]>,
required: true
},
}
)
const {title, recipes} = toRefs(props)
let numberOfCols = computed(() => {
const {name} = useDisplay()
const {t} = useI18n()
const {name} = useDisplay()
const loading = ref(true)
const recipes = ref([] as Recipe[] | RecipeOverview[])
const keyword = ref({} as Keyword)
/**
* determine title based on type
*/
const title = computed(() => {
switch (props.mode) {
case 'recent':
return t('Recently_Viewed')
case 'new':
return t('New')
case 'rating':
return t('Rating')
case 'keyword':
if (Object.keys(keyword.value).length > 0) {
return keyword.value.label
}
return t('Keyword')
}
})
/**
* determine icon based on type
*/
const icon = computed(() => {
switch (props.mode) {
case 'recent':
return 'fa-solid fa-eye'
case 'new':
return 'fa-solid fa-calendar-alt'
case 'rating':
return 'fa-solid fa-star'
case 'keyword':
return 'fa-solid fa-tags'
}
})
/**
* number of columns to show depending on display size
*/
const numberOfCols = computed(() => {
return homePageCols(name.value)
})
type CustomWindow = {
id: number,
recipes: Array<Recipe | RecipeOverview>
onMounted(() => {
loadRecipes()
})
/**
* load recipes depending on type by creating request parameters and executing request function
*/
function loadRecipes() {
let api = new ApiApi()
let requestParameters = {pageSize: 16} as ApiRecipeListRequest
switch (props.mode) {
case 'recent':
// TODO implement correct parameter
requestParameters._new = 'true'
break;
case 'new':
requestParameters._new = 'true'
break;
case 'rating':
requestParameters.rating = 4
break;
case 'keyword':
api.apiKeywordList({random: "true", limit: "1"}).then((r) => {
if (r.count > 0) {
keyword.value = r.results[0]
requestParameters.keywords = [keyword.value.id!]
doRecipeRequest(requestParameters)
}
})
return;
}
doRecipeRequest(requestParameters)
}
/**
* actual request function requesting the recipes from the server based on the given parameters
* @param params
*/
function doRecipeRequest(params: ApiRecipeListRequest) {
let api = new ApiApi()
api.apiRecipeList(params).then((r) => {
recipes.value = r.results
}).finally(() => {
loading.value = false
})
}
/**
* split the list of recipes into windows for display based on column count
*/
let recipeWindows = computed(() => {
let windows = []
let current_window = []