fix: migrate RecipeRating component to script setup and defineModel (#7203)

This commit is contained in:
ProperTeaMogul
2026-03-09 16:41:09 +00:00
committed by GitHub
parent 98c555fd20
commit 96597915ff
2 changed files with 55 additions and 74 deletions

View File

@@ -17,7 +17,7 @@
</v-card-title>
<RecipeRating
:key="recipe.slug"
:value="recipe.rating"
:model-value="recipe.rating"
:recipe-id="recipe.id"
:slug="recipe.slug"
/>

View File

@@ -1,10 +1,10 @@
<template>
<div @click.prevent>
<!-- User Rating -->
<v-hover v-slot="{ isHovering, props }">
<v-hover v-slot="{ isHovering, props: hoverProps }">
<v-rating
v-if="isOwnGroup && (userRating || isHovering || !ratingsLoaded)"
v-bind="props"
v-bind="hoverProps"
:model-value="userRating"
active-color="secondary"
color="secondary-lighten-3"
@@ -18,7 +18,7 @@
<!-- Group Rating -->
<v-rating
v-else
v-bind="props"
v-bind="hoverProps"
:model-value="groupRating"
:half-increments="true"
active-color="grey-darken-1"
@@ -32,81 +32,62 @@
</div>
</template>
<script lang="ts">
<script setup lang="ts">
import { useLoggedInState } from "~/composables/use-logged-in-state";
import { useUserSelfRatings } from "~/composables/use-users";
export default defineNuxtComponent({
props: {
emitOnly: {
type: Boolean,
default: false,
},
recipeId: {
type: String,
default: "",
},
slug: {
type: String,
default: "",
},
modelValue: {
type: Number,
default: 0,
},
small: {
type: Boolean,
default: false,
},
},
emits: ["update:modelValue"],
setup(props, context) {
const { isOwnGroup } = useLoggedInState();
const { userRatings, setRating, ready: ratingsLoaded } = useUserSelfRatings();
interface Props {
emitOnly?: boolean;
recipeId?: string;
slug?: string;
small?: boolean;
}
const userRating = computed(() => {
return userRatings.value.find(r => r.recipeId === props.recipeId)?.rating ?? undefined;
});
// if a user unsets their rating, we don't want to fall back to the group rating since it's out of sync
const hideGroupRating = ref(!!userRating.value);
watch(
() => userRating.value,
() => {
if (userRating.value) {
hideGroupRating.value = true;
}
},
);
const groupRating = computed(() => {
return hideGroupRating.value ? 0 : props.modelValue;
});
function updateRating(val?: number) {
if (!isOwnGroup.value) {
return;
}
if (val === userRating.value) {
val = 0;
}
if (!props.emitOnly) {
setRating(props.slug, val || 0, null);
}
context.emit("update:modelValue", val);
}
return {
isOwnGroup,
ratingsLoaded,
groupRating,
userRating,
updateRating,
};
},
const props = withDefaults(defineProps<Props>(), {
emitOnly: false,
recipeId: "",
slug: "",
small: false,
});
const modelValue = defineModel<number>({ default: 0 });
const { isOwnGroup } = useLoggedInState();
const { userRatings, setRating, ready: ratingsLoaded } = useUserSelfRatings();
const userRating = computed(() => {
return userRatings.value.find(r => r.recipeId === props.recipeId)?.rating ?? undefined;
});
// if a user unsets their rating, we don't want to fall back to the group rating since it's out of sync
const hideGroupRating = ref(!!userRating.value);
watch(
() => userRating.value,
() => {
if (userRating.value) {
hideGroupRating.value = true;
}
},
);
const groupRating = computed(() => {
return hideGroupRating.value ? 0 : modelValue.value;
});
function updateRating(val?: number) {
if (!isOwnGroup.value) {
return;
}
if (val === userRating.value) {
val = 0;
}
if (!props.emitOnly) {
setRating(props.slug, val || 0, null);
}
modelValue.value = val ?? 0;
}
</script>
<style lang="scss" scoped></style>