332 lines
7.9 KiB
TypeScript
332 lines
7.9 KiB
TypeScript
import { defineStore } from "pinia";
|
|
import { ref } from "vue";
|
|
import { io } from "socket.io-client";
|
|
import http from "@/plugins/http";
|
|
import config from "@/app.config";
|
|
|
|
import { useCounterMixin } from "@/stores/mixin";
|
|
import type {
|
|
SupportMessageResponse,
|
|
SupportIssueResponse,
|
|
SupportStatusUser,
|
|
SupportMessageStatus,
|
|
SupportIssueCategoryResponse,
|
|
} from "@/modules/00_support/interface/index/Main";
|
|
import keycloak from "@/plugins/keycloak";
|
|
import { useQuasar } from "quasar";
|
|
|
|
export const useSupportStore = defineStore("supportServiceStore", () => {
|
|
const { showLoader, hideLoader, messageError } = useCounterMixin();
|
|
const $q = useQuasar();
|
|
const userId = ref<string | undefined>(keycloak.subject);
|
|
const issue = ref<SupportIssueResponse>();
|
|
const message = ref<SupportMessageResponse>();
|
|
const messageStatus = ref<SupportMessageStatus>();
|
|
const userStatus = ref<SupportStatusUser[]>([]);
|
|
const currentIssue = ref<string>("");
|
|
const currentTitle = ref<string>("");
|
|
const currentCategoryId = ref<string>("");
|
|
const correntStatusIssue = ref<"new" | "ongoing" | "resolved">("new");
|
|
const currentTotalMessage = ref<number>();
|
|
const currentPage = ref<number>();
|
|
const scrollContainer = ref();
|
|
const currentPageIssue = ref<number>();
|
|
const currentTotalIssue = ref<number>();
|
|
const currentCategory = ref<string>();
|
|
const createdByUserId = ref<string>("");
|
|
const createdByUserName = ref<string>("");
|
|
|
|
const rowsCategory = ref<SupportIssueCategoryResponse>();
|
|
|
|
function scrollToEnd(position: Number = 1) {
|
|
setTimeout(() => {
|
|
scrollContainer.value?.setScrollPercentage("vertical", position);
|
|
}, 150);
|
|
}
|
|
|
|
const socket = io(config.API.supportSocket, {
|
|
auth: { token: keycloak.token },
|
|
autoConnect: false,
|
|
path: "/api/v1/support/socket/",
|
|
});
|
|
|
|
socket.on("users", (data: SupportStatusUser[]) => {
|
|
userStatus.value = data;
|
|
});
|
|
|
|
socket.on("online", (r) => {
|
|
userStatus.value.push({
|
|
socketId: r.socketId,
|
|
userId: r.userId,
|
|
name: r.name,
|
|
role: r.role,
|
|
});
|
|
});
|
|
|
|
socket.on("offline", (socketId: string) => {
|
|
if (socketId === socket.id) return;
|
|
userStatus.value = userStatus.value.filter((v) => v.socketId !== socketId);
|
|
});
|
|
|
|
socket.on("notify-message", (r) => {
|
|
if (issue.value) {
|
|
issue.value.result = issue.value.result.map((v) => {
|
|
if (v.id === r.issueId) {
|
|
v.unreadCount++;
|
|
v.lastMessage = r.content;
|
|
v.updatedAt = r.updatedAt;
|
|
}
|
|
if (currentIssue.value === r.issueId) {
|
|
v.unreadCount = 0;
|
|
}
|
|
return v;
|
|
});
|
|
}
|
|
});
|
|
|
|
socket.on("read", (r) => {
|
|
if (messageStatus.value) {
|
|
messageStatus.value.result = messageStatus.value.result.map((v) => {
|
|
if (v.fromUserId === r.fromUserId) return r;
|
|
return v;
|
|
});
|
|
}
|
|
});
|
|
|
|
socket.on("message", (r) => {
|
|
message.value?.result.message.push(r);
|
|
|
|
if (issue.value) {
|
|
issue.value.result = issue.value.result.map((v) => {
|
|
if (v.id === r.issueId) {
|
|
v.lastMessage = r.content;
|
|
v.updatedAt = r.updatedAt;
|
|
}
|
|
return v;
|
|
});
|
|
}
|
|
|
|
socket.emit("mark-read", { issueId: currentIssue.value });
|
|
scrollToEnd();
|
|
});
|
|
|
|
function sendMessage(content: string, to: string) {
|
|
socket.emit("message", { to, content });
|
|
scrollToEnd();
|
|
}
|
|
|
|
async function fetchMessageStatus(issueId: string) {
|
|
const res = await http
|
|
.get(config.API.supportMessageStatus(issueId))
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {});
|
|
|
|
if (res && res.data) {
|
|
messageStatus.value = res.data;
|
|
}
|
|
}
|
|
|
|
async function loadMessage(page: number) {
|
|
const res = await http
|
|
.get(`${config.API.supportMessage(currentIssue.value)}?page=${page}`)
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
});
|
|
|
|
if (res && res.data) {
|
|
message.value?.result.message.unshift(...res.data.result.message);
|
|
currentPage.value = res.data.page;
|
|
}
|
|
}
|
|
|
|
async function fetchMessage(issueId: string) {
|
|
showLoader();
|
|
const res = await http
|
|
.get(config.API.supportMessage(issueId))
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
|
|
if (res && res.data) {
|
|
message.value = await res.data;
|
|
message.value?.result.message.reverse();
|
|
currentPage.value = res.data.page;
|
|
currentTotalMessage.value = res.data.total;
|
|
socket.emit("join-issue", { issueId });
|
|
socket.emit("mark-read", { issueId });
|
|
scrollToEnd();
|
|
}
|
|
}
|
|
|
|
async function ChangeStatusIssue(
|
|
issueId: string,
|
|
title: string,
|
|
categoryId: string,
|
|
status: "new" | "ongoing" | "resolved"
|
|
) {
|
|
showLoader();
|
|
const requestBody = {
|
|
title: title,
|
|
categoryId: categoryId,
|
|
status: status,
|
|
};
|
|
|
|
const res = await http
|
|
.patch(config.API.supportIssueChangeStatus(issueId), requestBody)
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
if (res) {
|
|
fetchIssue();
|
|
correntStatusIssue.value = status;
|
|
}
|
|
}
|
|
|
|
async function fetchIssue(page: number = 1) {
|
|
showLoader();
|
|
const res = await http
|
|
.get(`${config.API.supportIssue}?page=${page}&pageSize=30`)
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
|
|
if (res && res.data) {
|
|
issue.value = res.data;
|
|
currentPageIssue.value = res.data.page;
|
|
currentTotalIssue.value = res.data.total;
|
|
}
|
|
}
|
|
|
|
async function searchIssue(input: string) {
|
|
showLoader();
|
|
const res = await http
|
|
.get(config.API.supportSearchIssue(input))
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
|
|
if (res && res.data) {
|
|
issue.value = res.data;
|
|
currentPageIssue.value = res.data.page;
|
|
currentTotalIssue.value = res.data.total;
|
|
}
|
|
}
|
|
|
|
async function newCategory(name: string) {
|
|
showLoader();
|
|
const res = await http
|
|
.post(config.API.supportCategory, {
|
|
name: name,
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
|
|
if (res) {
|
|
fetchCategory();
|
|
}
|
|
}
|
|
|
|
async function fetchCategory() {
|
|
showLoader();
|
|
const res = await http
|
|
.get(config.API.supportCategory)
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
if (res && res.data) {
|
|
rowsCategory.value = res.data;
|
|
}
|
|
}
|
|
|
|
async function deleteCategory(CategoryId: string) {
|
|
showLoader();
|
|
const res = await http
|
|
.delete(config.API.supportCategoryAction(CategoryId))
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
|
|
if (res) {
|
|
fetchCategory();
|
|
}
|
|
}
|
|
|
|
async function editCategory(CategoryId: string, name: string) {
|
|
showLoader();
|
|
const res = await http
|
|
.patch(config.API.supportCategoryAction(CategoryId), {
|
|
name: name,
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
|
|
if (res) {
|
|
fetchCategory();
|
|
}
|
|
}
|
|
|
|
return {
|
|
userId,
|
|
issue,
|
|
message,
|
|
scrollContainer,
|
|
currentIssue,
|
|
currentTitle,
|
|
socket,
|
|
messageStatus,
|
|
currentTotalMessage,
|
|
currentPage,
|
|
currentPageIssue,
|
|
currentTotalIssue,
|
|
currentCategoryId,
|
|
correntStatusIssue,
|
|
currentCategory,
|
|
rowsCategory,
|
|
userStatus,
|
|
createdByUserId,
|
|
createdByUserName,
|
|
fetchIssue,
|
|
fetchMessage,
|
|
fetchMessageStatus,
|
|
sendMessage,
|
|
scrollToEnd,
|
|
loadMessage,
|
|
ChangeStatusIssue,
|
|
newCategory,
|
|
fetchCategory,
|
|
deleteCategory,
|
|
editCategory,
|
|
searchIssue,
|
|
};
|
|
});
|