complete ticket section

This commit is contained in:
HAM!DREZA
2024-06-28 15:44:08 +03:30
parent 6b6b6d53aa
commit d2734cddee
14 changed files with 948 additions and 106 deletions
+1
View File
@@ -41,6 +41,7 @@ declare module 'vue' {
RouterView: typeof import('vue-router')['RouterView']
SecondStep: typeof import('./src/components/ProductFormSteps/SecondStep.vue')['default']
Sidebar: typeof import('primevue/sidebar')['default']
Tag: typeof import('primevue/tag')['default']
Textarea: typeof import('primevue/textarea')['default']
TheWelcome: typeof import('./src/components/TheWelcome.vue')['default']
ThirdStep: typeof import('./src/components/ProductFormSteps/ThirdStep.vue')['default']
+1 -1
View File
@@ -106,7 +106,7 @@ const items = ref([
{
label: t('addVideo'),
icon: 'pi pi-file-edit',
command: () => router.push('/courses/update')
command: () => router.push('/videos')
},
]
+20 -5
View File
@@ -53,11 +53,11 @@ const router = createRouter({
// name: 'Orders',
// component: () => import('@/views/Orders.vue'),
// },
// {
// path: '/comments',
// name: 'Comments',
// component: () => import('@/views/Comments.vue'),
// },
{
path: '/comments',
name: 'Comments',
component: () => import('@/views/Comments.vue'),
},
{
path: '/users',
name: 'Users',
@@ -83,6 +83,11 @@ const router = createRouter({
name: 'EditCoupon',
component: () => import('@/views/EditCoupon.vue'),
},
{
path: '/comments/:id',
name: 'Answer',
component: () => import('@/views/AnswerComment.vue'),
},
{
path: '/tickets/:id',
name: 'ShowTickets',
@@ -93,6 +98,16 @@ const router = createRouter({
name: 'Tickets',
component: () => import('@/views/Tickets.vue'),
},
{
path: '/videos',
name: 'Videos',
component: () => import('@/views/Videos.vue'),
},
{
path: '/videos/:id',
name: 'AddVideos',
component: () => import('@/views/AddVideos.vue'),
},
{
path: '/pages',
children: [
+83
View File
@@ -0,0 +1,83 @@
import axios from '../plugins/axios'
import { defineStore } from 'pinia'
export const useHeadlinesStore = defineStore('headlines', {
state: () => ({
items: [],
brands: [],
categories: [],
fetching: true,
total: 0
}),
actions: {
async index(courseId) {
this.items = [];
this.fetching = true
const { status, data } = await axios.get('/courseHeadline', courseId)
this.fetching = false
return data
},
async create(newCourse) {
const { status, data } = await axios.post('/course', newCourse)
return data
},
async delete(id) {
const { status, data } = await axios.delete(`/course/${id}`, id)
return data
},
async edit(id) {
const { status, data } = await axios.get(`/course/${id}`)
return data
},
// async store(form) {
// const result = await axios.post('/admin/products/add', form)
// if (result.status === 201)
// this.items.unshift(result.data)
// return result;
// },
// async update(id, form) {
// const result = await axios.put(`/admin/products/${id}`, form)
// if (result.status === 200) {
// const index = this.items.findIndex(({ _id }) => _id == id)
// this.items[index] = result.data
// }
// return result;
// },
// async confirm(id, form) {
// const result = await axios.post(`/admin/products/confirm/${id}`, form)
// if (result.status === 200) {
// const index = this.items.findIndex(({ _id }) => _id == id)
// this.items[index] = result.data
// }
// return result;
// },
// async remove(id) {
// const result = await axios.delete(`/admin/products/${id}`)
// if (result.status === 200) {
// const index = this.items.findIndex(({ _id }) => _id == id)
// this.items.splice(index, 1)
// }
// return result;
// },
}
})
+178
View File
@@ -0,0 +1,178 @@
import axios from '../plugins/axios'
import { defineStore } from 'pinia'
export const useCommentStore = defineStore('comments', {
state: () => ({
items: [],
fetching: true,
total: 0
}),
getters: {
// treeSelect: (state) => (id = null) => {
// if (id) {
// const foreach = (items) => {
// return items.filter((item) => {
// if (item.key != id) {
// if (item.children)
// item.children = foreach(item.children)
// return true
// } else return false
// })
// }
// return foreach(state.items)
// }
// return state.items
// },
find: (state) => (id) => {
if (id) {
const foreach = (items) => {
const item = items.find(({ key }) => key == id)
if (item) return item
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.children) {
const temp = foreach(item.children)
if (temp) return temp
}
}
}
return foreach(state.items)
}
return '';
}
},
actions: {
async reply(id, body) {
this.fetching = true
const data = await axios.post(`/course/${id}/comment`, body)
this.fetching = false
console.log(id, 'id');
return data
if (status === 200) {
const map = (items, parent = null) => {
return items.map((item) => {
const temp = {
key: item._id,
label: item.name,
data: item
}
if (parent)
temp.data.parentCategoryID = { [parent]: true }
if (item.sub) {
temp.children = map(item.sub, temp.key)
delete temp.data.sub
}
return temp;
});
}
this.items = map(data)
// this.items = data.items
// this.total = data.total
}
},
async ticket(id) {
this.fetching = true
const { status, data } = await axios.get(`/ticket/${id}`)
this.fetching = false
return data
if (status === 200) {
const map = (items, parent = null) => {
return items.map((item) => {
const temp = {
key: item._id,
label: item.name,
data: item
}
if (parent)
temp.data.parentCategoryID = { [parent]: true }
if (item.sub) {
temp.children = map(item.sub, temp.key)
delete temp.data.sub
}
return temp;
});
}
this.items = map(data)
// this.items = data.items
// this.total = data.total
}
},
async close(id){
this.fetching = true
const { status, data } = await axios.patch(`/ticket/close/${id}`, id)
this.fetching = false
return data
if (status === 200) {
const map = (items, parent = null) => {
return items.map((item) => {
const temp = {
key: item._id,
label: item.name,
data: item
}
if (parent)
temp.data.parentCategoryID = { [parent]: true }
if (item.sub) {
temp.children = map(item.sub, temp.key)
delete temp.data.sub
}
return temp;
});
}
this.items = map(data)
// this.items = data.items
// this.total = data.total
}
},
async create(id) {
const result = await axios.post('/courseCategory', {
name: id.value
})
//console.log('result', result);
return result;
},
async store(form) {
const result = await axios.post('/admin/categories', form)
if (result.status === 201)
this.items.unshift(result.data)
return result;
},
async update(id, form) {
const result = await axios.put(`/admin/categories/${id}`, form)
if (result.status === 200) {
const index = this.items.findIndex(({ _id }) => _id == id)
this.items[index] = result.data
}
return result;
},
async remove(id) {
const result = await axios.delete(`/courseCategory/${id}`)
if (result.status === 200) {
const index = this.items.findIndex(({ _id }) => _id == id)
this.items.splice(index, 1)
}
return result;
},
}
})
-11
View File
@@ -57,17 +57,6 @@ export const useStaticsStore = defineStore('statics', {
},
async edit(data) {
this.fetching = true
// const json = {
// "about": "",
// "student": 100,
// "hours": 0,
// "title": 0,
// "expertise": 0,
// "nameCompany": "string",
// "mission": "string",
// "start": "string",
// "goals": "string"
// }
const result = await axios.patch('/admin/settings/edit', data)
this.fetching = false
return result
+9 -19
View File
@@ -24,7 +24,7 @@
</div>
<div class="flex flex-col gap-1">
<FloatLabel>
<InputText class="w-full" v-model="data.videosCount" />
<InputText class="w-full" v-model="data.hours" />
<label>{{ $t("تعداد ساعات آموزشی") }}</label>
</FloatLabel>
</div>
@@ -57,24 +57,13 @@
import { useStaticsStore } from "@/stores/statics";
import { useRoute } from "vue-router";
const data = reactive({
about: "string",
student: 0,
hours: 0,
title: 0,
expertise: 0,
nameCompany: "string",
mission: "string",
start: "string",
goals: "string",
// description: "",
// videosCount: null,
// rates: null,
student: 0,
title: 0,
hours: 0,
});
const save = async (data) => {
console.log('form', data);
console.log('json', JSON.stringify(data));
const { result } = await store.edit(data);
console.log("res", result);
const result = await store.edit(data);
};
const expandedKeys = ref({});
@@ -88,9 +77,10 @@
watchEffect(async () => {
await store.index();
// console.log(store.items);
data.student = store.items.student;
//data.videosCount = store.items.hours;
data.expertise = store.items.expertise;
data.student = store.items.student;
data.title = store.items.title;
data.hours = store.items.hours;
});
</script>
+24
View File
@@ -0,0 +1,24 @@
<template>
<h2>add</h2>
{{ videos }}
</template>
<script setup>
import { ref, watchEffect } from "vue";
import { useRoute } from "vue-router";
import { useHeadlinesStore } from "@/stores/Headlines"
const store = useHeadlinesStore()
const route = useRoute()
const videos = ref([])
watchEffect(async() => {
videos.value = await store.index({
courseId: route.params.id
})
console.log(videos);
})
</script>
+63 -25
View File
@@ -1,31 +1,69 @@
<template>
ادمین ها
<input id="avatar" ref="files" name="file" type="file" @change="change">
<Panel :header="$t('admins')">
<DataTable :value="admins">
<Column class="w-16">
<template #body="{ data: { avatarMedia } }">
<Avatar
:image="avatarMedia"
size="large"
shape="circle"
class="transition-transform hover:scale-150"
/>
</template>
</Column>
<Column field="name" :header="$t('name')" />
<Column field="id" :header="$t('id')" />
<Column field="phone" :header="$t('phoneNumber')" />
<Column field="statusText" :header="$t('status')" />
<Column field="userName" :header="$t('username')" />
<Column headerClass="w-32">
<template #body="{ data }">
<div class="flex justify-end">
<Button
icon="pi pi-eye"
rounded
text
severity="secondary"
@click="show(data)"
/>
</div>
</template>
</Column>
<template #empty>
<p>{{ store.fetching ? $t("loading") : $t("emptyTable") }}</p>
</template>
<template #footer>
<!--
<Paginator :rows="store.total" :totalRecords="store.total" :rowsPerPageOptions="[5, 20, 30]"></Paginator>
-->
<Pagination :total="store.total" />
</template>
</DataTable>
</Panel>
</template>
<script setup>
import { useUsersStore } from "@/stores/users";
import { inject, reactive, defineAsyncComponent, ref, watchEffect } from "vue";
const store = useUsersStore();
const admins = ref()
import { useUploaderStore } from "@/stores/uploader";
const avatar = document.querySelector("#avatar");
const store = useUploaderStore()
//const files = ref(null)
const change = async (avatar) => {
const data = await store.uploader(avatar.target.value)
}
const UserDetails = defineAsyncComponent(() =>
import("../components/UserDetails.vue")
);
const { dialog, t } = inject("service");
const show = (user) => {
dialog.open(UserDetails, {
props: { modal: true, closable: true, header: t("userDetails") },
data: { user, confirm: store.confirm },
});
};
watchEffect(async () => {
await store.index(1, 100);
console.log("user", store.items);
admins.value = store.items.filter(item => item.roles[1] === 'Admin' );
console.log('filter',admins);
});
</script>
+125
View File
@@ -0,0 +1,125 @@
<template>
<Panel :header="$t('پاسخ به نظرات')">
<div v-for="item in data.comments" :key="item.id">
<div class="card mb-8">
<Panel toggleable>
<template #header>
<div class="flex items-center gap-2">
<Avatar :image="item.createdBy.avatarMedia" size="large" shape="circle" />
<span class="font-bold">{{item.createdBy.name}}</span>
</div>
</template>
<template #footer>
<div class="flex flex-wrap items-center justify-between gap-4">
<div class="flex items-center gap-2">
<Button icon="pi pi-reply" rounded text @click="reply(item.id)"></Button>
<Tag v-if="item.replies.length === 0" icon="pi pi-times" class="gap-1" severity="danger" value="در انتظار پاسخ"></Tag>
<Tag v-else icon="pi pi-check" severity="success" class="gap-1" value="پاسخ داده شده"></Tag>
</div>
<span class="text-surface-500 dark:text-surface-400">{{ jDate(item.createdAt) }}</span>
</div>
</template>
<template #icons>
<Menu ref="menu" id="config_menu" :model="items" popup />
</template>
<p class="m-0">
{{ item.text }}
</p>
<p v-for="answr in item.replies" :key="answr.id" class="border rounded-md ms-[60px] mt-2 p-2">{{answr.text}}</p>
</Panel>
</div>
</div>
<Textarea v-model="value" placeholder="پاسخ..." class="w-full" rows="5" />
<div class="flex pt-4 justify-end">
<Button
:label="$t('send')"
icon="pi pi-send"
severity="success"
:loading="saving"
@click="sendReply"
/>
</div>
</Panel>
</template>
<script setup>
import { useToast } from "primevue/usetoast";
import { useRouter } from 'vue-router';
import Menu from 'primevue/menu';
import {jDate} from "@/utils/jDate";
import { ref, watchEffect } from "vue";
import { useRoute } from "vue-router";
import {useProductsStore} from "@/stores/products";
import {useCommentStore} from "@/stores/courseComments"
const store = useProductsStore()
const commentStore = useCommentStore()
const route = useRoute()
const data = ref([])
const menu = ref(null);
const toast = useToast();
const router = useRouter();
const replyTarget = ref(null)
const value = ref(null)
const reply = (id) =>{
replyTarget.value = id
}
const sendReply = async() =>{
if (replyTarget.value === null || replyTarget.value === '') {
return console.log('کامنت مورد نظر را انتخاب کنید');
}
if (value.value === null || value.value === '') {
return console.log('متن پیام را وارد کنید');
}
// console.log(value.value);
const rep = await commentStore.reply(route.params.id, {
text: value.value,
parent: replyTarget.value
})
console.log('rep', rep);
}
const items = ref([
{
label: 'Refresh',
icon: 'pi pi-refresh'
},
{
label: 'Search',
icon: 'pi pi-search'
},
{
separator: true
},
{
label: 'Delete',
icon: 'pi pi-times'
}
]);
const toggle = (event) => {
menu.value.toggle(event);
};
const save = () => {
toast.add({ severity: 'success', summary: 'Success', detail: 'Data Saved', life: 3000 });
};
watchEffect(async() => {
data.value = await store.edit(route.params.id)
console.log('store', data.value.comments);
})
</script>
+212
View File
@@ -0,0 +1,212 @@
<template>
<Panel :header="$t('comments')">
<DataTable :value="store.items">
<Column class="w-16" :header="$t('image')">
<template #body="{ data: { image } }">
<Avatar
:image="image"
size="large"
shape="circle"
class="transition-transform hover:scale-150"
/>
</template>
</Column>
<Column field="name" :header="$t('name')" />
<Column
:field="({ categories }) => categories[0].name"
:header="$t('category')"
/>
<Column field="price" :header="$t('price')" />
<Column
:field="({ createdAt }) => jDate(createdAt)"
:header="$t('createdAt')"
class="w-28"
/>
<Column
:field="({ updatedAt }) => jDate(updatedAt)"
:header="$t('updatedAt')"
class="w-32 text-center"
/>
<Column field="averageRating" :header="$t('امتیاز')" />
<Column :header="$t('مشاهده نظرات')" headerClass="w-32">
<template #body="{ data }">
<div class="flex justify-end">
<Button icon="pi pi-eye" rounded text severity="secondary" @click="show(data)" />
</div>
</template>
</Column>
<!-- <Column :field="({ price }) => numberFormat(price)" :header="$t('price')" />
<Column :header="$t('category')" class="whitespace-nowrap">
<template #body="{ data: { category } }">
<span v-if="category.length > 0">
{{ category.slice(-1)[0].name }}
</span>
</template>
</Column>
<Column field="name" :header="$t('reviews')">
<template #body="{ data: { name } }">
<Rating :modelValue="name" readonly :cancel="false" class="[&_svg]:text-yellow-400" />
</template>
</Column>
<Column :header="$t('status')">
<template #body="{ data: { confirmToShow, _id } }">
<Tag v-if="!confirmToShow" value="غیر فعال" severity="danger" @click="accepter(_id,true)"/>
<Tag v-if="confirmToShow" value="فعال" severity="success" @click="accepter(_id,false)"/>
</template>
</Column>
<Column :field="({ createdAt }) => jDate(createdAt)" :header="$t('createdAt')" class="w-28" />
<Column :field="({ updatedAt }) => jDate(updatedAt)" :header="$t('updatedAt')" class="w-32 text-center" />
<Column headerClass="w-32">
<template #body="{ data }">
<div class="flex justify-end">
<Button icon="pi pi-eye" rounded text severity="secondary" @click="show(data)" />
<Button icon="pi pi-pencil" rounded text severity="secondary" @click="edit(data)" />
<Button icon="pi pi-trash" rounded text severity="danger" :loading="data.removing"
@click="remove(data)" />
</div>
</template>
</Column> -->
<template #empty>
<p>{{ store.fetching ? $t("loading") : $t("emptyTable") }}</p>
</template>
<template #footer>
<Pagination :total="store.total" />
</template>
</DataTable>
<Galleria
v-model:visible="galleryVes"
:value="gallery"
:numVisible="5"
containerClass="w-1/2"
circular
fullScreen
showItemNavigators
:showThumbnailNavigators="false"
>
<template #item="{ item: { itemImageSrc, alt } }">
<img :src="itemImageSrc" :alt="alt" class="w-full block" />
</template>
</Galleria>
<Column headerClass="w-32">
<template #body="{ data }">
<div class="flex justify-end">
<Button
icon="pi pi-eye"
rounded
text
severity="secondary"
@click="show(data)"
/>
</div>
</template>
</Column>
</Panel>
</template>
<script setup>
import { useProductsStore } from '@/stores/products';
import { jDate } from '@/utils/jDate';
import { numberFormat } from '@/utils/numberFormat';
import { defineAsyncComponent, inject, onBeforeMount, ref, watchEffect } from 'vue';
import { useRoute, useRouter } from 'vue-router';
const ProductForm = defineAsyncComponent(() => import('../components/ProductForm.vue'));
const ProductDetails = defineAsyncComponent(() => import('../components/ProductDetails.vue'));
const { toast, dialog, confirm, t } = inject('service')
var gallery = []
const galleryVes = ref(false)
const openGallery = (images =>{
gallery = []
images.map(image =>{
gallery.push({itemImageSrc:image, alt:"product"})
})
galleryVes.value = true
})
const router = useRouter()
const show = (data) => {
console.log(data);
router.push(`/comments/${data._id}`)
}
const UserDetails = defineAsyncComponent(() => import('../components/UserDetails.vue'));
const store = useProductsStore()
const route = useRoute()
const edit = (data) =>{
router.push(data._id)
}
const remove = (data) => {
console.log('done', data._id)
confirm.require({
message: t('Are you sure you want to proceed?'),
header: t('Danger Zone'),
icon: 'pi pi-info-circle',
acceptClass: 'p-button-danger p-button-sm',
rejectClass: 'p-button-secondary p-button-outlined p-button-sm',
rejectLabel: t('cancel'),
acceptLabel: t('beOmitted'),
defaultFocus: 'reject',
accept: async () => {
const deleted = await store.delete(data._id)
console.log(deleted);
await store.index()
}
// product.removing = true
// const { status, data } = await store.remove(product._id);
// product.removing = false
// if (status === 200)
// toast.add({
// severity: 'success', summary: t('successful'), detail: t('destroySuccessfully'), life: 3000
// });
// else
// toast.add({
// severity: 'error', summary: t('error'), detail: data.msg, life: 3000
// });
// },
});
}
watchEffect(async() => {
const { page = 1, pageSize = 10 } = route.query
await store.index(page, pageSize)
console.log(store.items[2].image);
console.log(String.fromCharCode(store.items[2].image)).join('');
// store.items.forEach((product) => {
// product.status = { value: t('active'), severity: 'success' };
// })
})
const accepter = async (id,confirmToShow)=>{
const { status, data } = await store.confirm(id, {confirmToShow});
if (status === 200)
toast.add({
severity: 'success', summary: t('successful'), detail: t('destroySuccessfully'), life: 3000
});
else
toast.add({
severity: 'error', summary: t('error'), detail: data.msg, life: 3000
});
}
</script>
<style lang="scss" scoped></style>
+10 -14
View File
@@ -24,7 +24,7 @@
</div>
<div class="flex flex-col gap-1">
<FloatLabel>
<InputText class="w-full" v-model="data.videosCount" />
<InputText class="w-full" v-model="data.expertise" />
<label>{{ $t("تعداد ویدیو های آموزشی") }}</label>
</FloatLabel>
</div>
@@ -80,24 +80,17 @@ import {
import { useStaticsStore } from "@/stores/statics";
import { useRoute } from "vue-router";
const data = reactive({
about: "string",
student: 0,
hours: 0,
title: 0,
expertise: 0,
nameCompany: "string",
mission: "string",
start: "string",
goals: "string",
// description: "",
// videosCount: null,
// rates: null,
about: "string",
});
const save = async (data) => {
console.log('form', data);
console.log('json', JSON.stringify(data));
const { result } = await store.edit(data);
console.log("res", result);
// console.log('form', data);
// console.log('json', JSON.stringify(data));
const result = await store.edit(data);
// console.log("res", result);
};
const expandedKeys = ref({});
@@ -113,6 +106,9 @@ watchEffect(async () => {
await store.index();
// console.log(store.items);
data.student = store.items.student;
data.title = store.items.title;
data.expertise = store.items.expertise;
data.about = store.items.about;
//data.videosCount = store.items.hours;
});
</script>
+27 -31
View File
@@ -1,35 +1,30 @@
<template>
<Panel :header="$t('گفتگو')">
<!-- <DataTable :value="messages.ticketMessages">
<Column field="content" :header="$t('متن تیکت')" />
<Column field="id" :header="$t('id')" />
<Column :field="({createdAt}) => jDate(createdAt)" :header="$t('createdAt')" />
<Column :header="$t('options')" headerClass="w-32">
<template #body="{ data }">
<div class="flex justify-end">
<Button
icon="pi pi-reply"
rounded
text
severity="secondary"
@click="edit(data)"
/>
</div></template></Column>
<template #empty>
<p>{{ store.fetching ? $t("loading") : $t("emptyTable") }}</p>
</template>
</DataTable> -->
<div v-for="item in messages.ticketMessages" :key="item.id">
<!-- <Textarea :value="item.content" cols="30" disabled /> -->
<Fieldset legend="متن تیکت" class="mb-8" :class="{'bg-gray-100' : item.createdBy.roles[0] === 'Admin'}">
<p class="m-0">
{{ item.content }}
</p>
</Fieldset>
<div v-for="item in messages" :key="item.id" >
<div class="card mb-8">
<Panel toggleable>
<template #header >
<div class="flex items-center gap-2">
<Avatar :image="item.createdBy.avatarMedia" size="large" shape="circle" />
<span class="font-bold">{{item.createdBy.name}}</span>
<Tag v-if="item.createdBy.roles[0] === 'Admin'" class="gap-1" icon="pi pi-user" severity="info" value="ادمین"></Tag>
<Tag v-else class="gap-1" icon="pi pi-user" severity="success" value="کاربر"></Tag>
</div>
</template>
<template #footer>
<div class="flex flex-wrap items-center justify-end">
<span class="text-surface-500 dark:text-surface-400">{{ jDate(item.createdAt) }}</span>
</div>
</template>
<p class="m-0">
{{ item.content }}
</p>
</Panel>
</div>
<Editor v-model="value" editorStyle="height: 320px" />
</div>
<Textarea v-model="value" placeholder="پاسخ..." class="w-full" rows="5" />
<div class="flex pt-4 justify-end">
<Button
:label="$t('send')"
@@ -61,8 +56,9 @@ const send = async (value) => {
console.log('sended', sended);
};
watchEffect(async () => {
messages.value = await store.ticket(route.params.id);
console.log("mess", messages.value.ticketMessages);
const data = await store.ticket(route.params.id);
messages.value = data.ticketMessages.reverse()
console.log("mess", data);
});
</script>
+195
View File
@@ -0,0 +1,195 @@
<template>
<Panel :header="$t('مدیریت ویدیو ها')">
<DataTable :value="store.items">
<Column class="w-16" :header="$t('image')">
<template #body="{ data: { image } }">
<Avatar
:image="image"
size="large"
shape="circle"
class="transition-transform hover:scale-150"
/>
</template>
</Column>
<Column field="name" :header="$t('name')" />
<Column
:field="({ categories }) => categories[0].name"
:header="$t('category')"
/>
<Column field="price" :header="$t('price')" />
<Column
:field="({ createdAt }) => jDate(createdAt)"
:header="$t('createdAt')"
class="w-28"
/>
<Column
:field="({ updatedAt }) => jDate(updatedAt)"
:header="$t('updatedAt')"
class="w-32 text-center"
/>
<Column field="averageRating" :header="$t('امتیاز')" />
<Column :header="$t('options')" headerClass="w-32">
<template #body="{ data }">
<div class="flex justify-end">
<Button icon="pi pi-eye" rounded text severity="secondary" @click="show(data)" />
<Button
icon="pi pi-pencil"
rounded
text
severity="secondary"
@click="edit(data)"
/>
</div>
</template>
</Column>
<template #empty>
<p>{{ store.fetching ? $t("loading") : $t("emptyTable") }}</p>
</template>
<template #footer>
<Pagination :total="store.total" />
</template>
</DataTable>
<Galleria
v-model:visible="galleryVes"
:value="gallery"
:numVisible="5"
containerClass="w-1/2"
circular
fullScreen
showItemNavigators
:showThumbnailNavigators="false"
>
<template #item="{ item: { itemImageSrc, alt } }">
<img :src="itemImageSrc" :alt="alt" class="w-full block" />
</template>
</Galleria>
<Column headerClass="w-32">
<template #body="{ data }">
<div class="flex justify-end">
<Button
icon="pi pi-eye"
rounded
text
severity="secondary"
@click="show(data)"
/>
</div>
</template>
</Column>
</Panel>
</template>
<script setup>
import { useProductsStore } from '@/stores/products';
import { jDate } from '@/utils/jDate';
import { numberFormat } from '@/utils/numberFormat';
import { defineAsyncComponent, inject, onBeforeMount, ref, watchEffect } from 'vue';
import { useRoute, useRouter } from 'vue-router';
const ProductForm = defineAsyncComponent(() => import('../components/ProductForm.vue'));
const ProductDetails = defineAsyncComponent(() => import('../components/ProductDetails.vue'));
const { toast, dialog, confirm, t } = inject('service')
var gallery = []
const galleryVes = ref(false)
const openGallery = (images =>{
gallery = []
images.map(image =>{
gallery.push({itemImageSrc:image, alt:"product"})
})
galleryVes.value = true
})
const show = (product) => {
dialog.open(ProductDetails, {
props: { modal: true, closable: true, header: t('productDetails') },
data: {
product
}
});
}
const UserDetails = defineAsyncComponent(() => import('../components/UserDetails.vue'));
const store = useProductsStore()
const route = useRoute()
const router = useRouter()
const edit = (data) =>{
router.push(`/videos/${data._id}`)
}
const remove = (data) => {
console.log('done', data._id)
confirm.require({
message: t('Are you sure you want to proceed?'),
header: t('Danger Zone'),
icon: 'pi pi-info-circle',
acceptClass: 'p-button-danger p-button-sm',
rejectClass: 'p-button-secondary p-button-outlined p-button-sm',
rejectLabel: t('cancel'),
acceptLabel: t('beOmitted'),
defaultFocus: 'reject',
accept: async () => {
const deleted = await store.delete(data._id)
console.log(deleted);
await store.index()
}
// product.removing = true
// const { status, data } = await store.remove(product._id);
// product.removing = false
// if (status === 200)
// toast.add({
// severity: 'success', summary: t('successful'), detail: t('destroySuccessfully'), life: 3000
// });
// else
// toast.add({
// severity: 'error', summary: t('error'), detail: data.msg, life: 3000
// });
// },
});
}
watchEffect(async() => {
const { page = 1, pageSize = 10 } = route.query
await store.index(page, pageSize)
console.log(store.items[2].image);
console.log(String.fromCharCode(store.items[2].image)).join('');
// store.items.forEach((product) => {
// product.status = { value: t('active'), severity: 'success' };
// })
})
const accepter = async (id,confirmToShow)=>{
const { status, data } = await store.confirm(id, {confirmToShow});
if (status === 200)
toast.add({
severity: 'success', summary: t('successful'), detail: t('destroySuccessfully'), life: 3000
});
else
toast.add({
severity: 'error', summary: t('error'), detail: data.msg, life: 3000
});
}
</script>
<style lang="scss" scoped></style>