fix rpoduct comment frontend and limit 10 charecter for post id

This commit is contained in:
Parsa Nazer
2026-05-22 19:17:47 +03:30
2 changed files with 55 additions and 44 deletions
@@ -58,7 +58,10 @@ const formRules = computed(() => {
}, },
postal_code: { postal_code: {
required: helpers.withMessage("فیلد کد پستی الزامی می باشد", required), required: helpers.withMessage("فیلد کد پستی الزامی می باشد", required),
minLength: helpers.withMessage("فیلد کد پستی حداقل 10 کرکتر می باشد", minLength(10)), exactLength: helpers.withMessage("فیلد کد پستی باید دقیقا 10 کرکتر باشد", (value: unknown) => {
if (value === null || value === undefined) return false;
return String(value).length === 10;
}),
}, },
address: { address: {
required: helpers.withMessage("فیلد آدرس کامل الزامی می باشد", required), required: helpers.withMessage("فیلد آدرس کامل الزامی می باشد", required),
+51 -43
View File
@@ -5,6 +5,7 @@ import useGetComments from "~/composables/api/product/useGetComments";
import useCreateComment from "~/composables/api/product/useCreateComment"; import useCreateComment from "~/composables/api/product/useCreateComment";
import useRateProduct from "~/composables/api/product/useRateProduct"; import useRateProduct from "~/composables/api/product/useRateProduct";
import { useAuth } from "~/composables/api/auth/useAuth"; import { useAuth } from "~/composables/api/auth/useAuth";
import useGetProduct from "~/composables/api/product/useGetProduct";
// props // props
@@ -28,6 +29,7 @@ const selectedRating = ref(5);
const showMoreComments = ref(false); const showMoreComments = ref(false);
const { data: comments, refetch: refetchComments } = useGetComments(id); const { data: comments, refetch: refetchComments } = useGetComments(id);
const { refetch: refetchProduct } = useGetProduct(id);
const { mutateAsync: createComment, isPending: isCreateCommentPending } = useCreateComment(id); const { mutateAsync: createComment, isPending: isCreateCommentPending } = useCreateComment(id);
const { mutateAsync: rateProduct, isPending: isRateProductPending } = useRateProduct(props.product.slug); const { mutateAsync: rateProduct, isPending: isRateProductPending } = useRateProduct(props.product.slug);
@@ -80,6 +82,7 @@ const submitComment = async () => {
userComment.value = ""; userComment.value = "";
selectedRating.value = 5; selectedRating.value = 5;
await refetchProduct();
await refetchComments(); await refetchComments();
}; };
@@ -112,61 +115,66 @@ const limitedComments = computed(() => {
@submit.prevent="submitComment" @submit.prevent="submitComment"
class="flex flex-col gap-6" class="flex flex-col gap-6"
> >
<div <div v-if="token">
v-if="hasUserRated" <div
class="flex flex-col gap-3 px-4 py-3 bg-white rounded-lg border border-slate-300" v-if="hasUserRated"
> class="flex flex-col gap-3 px-4 py-3 bg-white rounded-lg border border-slate-300"
<div class="flex flex-col gap-2"> >
<span class="typo-p-xs text-slate-700 font-semibold">امتیاز قبلی شما</span> <div class="flex flex-col gap-2">
<span class="typo-p-xs text-slate-700 font-semibold">امتیاز قبلی شما</span>
<div class="flex items-center gap-1">
<button
v-for="star in 5"
:key="`prev-${star}`"
type="button"
disabled
class="size-9 rounded-full flex-center cursor-not-allowed opacity-75"
:class="
star <= (props.product.user_rating || 0) ? 'bg-amber-50' : 'bg-slate-50'
"
>
<Icon
name="ci:star-solid"
class="size-5"
:class="
star <= (props.product.user_rating || 0)
? '**:fill-yellow-500'
: '**:fill-slate-300'
"
/>
</button>
<span class="typo-p-sm font-semibold text-slate-600 mr-2">{{
props.product.user_rating
}}</span>
</div>
</div>
</div>
<div
v-else
class="flex flex-col gap-2"
>
<span class="typo-p-sm text-slate-500">امتیاز شما</span>
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">
<button <button
v-for="star in 5" v-for="star in 5"
:key="`prev-${star}`" :key="star"
type="button" type="button"
disabled class="size-9 rounded-full flex-center transition-colors"
class="size-9 rounded-full flex-center cursor-not-allowed opacity-75" :class="star <= selectedRating ? 'bg-amber-50' : 'bg-slate-50'"
:class="star <= (props.product.user_rating || 0) ? 'bg-amber-50' : 'bg-slate-50'" :disabled="!token || isCreateCommentPending || isRateProductPending"
@click="selectedRating = star"
> >
<Icon <Icon
name="ci:star-solid" name="ci:star-solid"
class="size-5" class="size-5"
:class=" :class="star <= selectedRating ? '**:fill-yellow-500' : '**:fill-slate-300'"
star <= (props.product.user_rating || 0)
? '**:fill-yellow-500'
: '**:fill-slate-300'
"
/> />
</button> </button>
<span class="typo-p-sm font-semibold text-slate-600 mr-2">{{ <span class="typo-p-sm font-semibold text-slate-500 mr-2">{{ selectedRating }}</span>
props.product.user_rating
}}</span>
</div> </div>
</div> </div>
</div> </div>
<div
v-else
class="flex flex-col gap-2"
>
<span class="typo-p-sm text-slate-500">امتیاز شما</span>
<div class="flex items-center gap-1">
<button
v-for="star in 5"
:key="star"
type="button"
class="size-9 rounded-full flex-center transition-colors"
:class="star <= selectedRating ? 'bg-amber-50' : 'bg-slate-50'"
:disabled="!token || isCreateCommentPending || isRateProductPending"
@click="selectedRating = star"
>
<Icon
name="ci:star-solid"
class="size-5"
:class="star <= selectedRating ? '**:fill-yellow-500' : '**:fill-slate-300'"
/>
</button>
<span class="typo-p-sm font-semibold text-slate-500 mr-2">{{ selectedRating }}</span>
</div>
</div>
<Input <Input
v-model="userTitle" v-model="userTitle"
:disabled="!token" :disabled="!token"
@@ -196,7 +204,7 @@ const limitedComments = computed(() => {
type="button" type="button"
class="rounded-full w-full" class="rounded-full w-full"
> >
وارد شوید برای ثبت نظر وارد شوید
</Button> </Button>
</NuxtLink> </NuxtLink>
</form> </form>