dashboard/frontend/src/views/TicketView.svelte
2022-06-04 22:43:05 +01:00

200 lines
5.2 KiB
Svelte

<div class="parent">
<div class="content">
<Card footer={false}>
<span slot="title">Support Teams</span>
<div slot="body" class="body-wrapper">
<div class="section">
<h2 class="section-title">Close Ticket</h2>
<form on:submit|preventDefault={closeTicket}>
<div class="row" style="max-height: 63px; align-items: flex-end"> <!-- hacky -->
<div class="col-3" style="margin-bottom: 0 !important;">
<Input label="Close Reason" placeholder="No reason specified" col1={true} bind:value={closeReason}/>
</div>
<div class="col-1">
<div style="margin-left: 30px">
<Button danger={true} icon="fas fa-lock">Close Ticket</Button>
</div>
</div>
</div>
</form>
</div>
<div class="section">
<h2 class="section-title">View Ticket</h2>
<DiscordMessages {ticketId} {isPremium} {messages} bind:container on:send={sendMessage} />
</div>
</div>
</Card>
</div>
</div>
<script>
import Card from "../components/Card.svelte";
import {notifyError, notifyRatelimit, withLoadingScreen} from '../js/util'
import Button from "../components/Button.svelte";
import axios from "axios";
import {API_URL} from "../js/constants";
import {setDefaultHeaders, getToken} from '../includes/Auth.svelte'
import Input from "../components/form/Input.svelte";
import {navigateTo} from "svelte-router-spa";
import DiscordMessages from "../components/DiscordMessages.svelte";
export let currentRoute;
let guildId = currentRoute.namedParams.id;
let ticketId = parseInt(currentRoute.namedParams.ticketid);
let closeReason = '';
let messages = [];
let isPremium = false;
let container;
let WS_URL = env.WS_URL || 'ws://172.26.50.75:3000';
function scrollContainer() {
container.scrollTop = container.scrollHeight;
}
async function closeTicket() {
let data = {
reason: closeReason,
};
const res = await axios.delete(`${API_URL}/api/${guildId}/tickets/${ticketId}`, {data: data});
if (res.status !== 200) {
notifyError(res.data.error);
return;
}
navigateTo(`/manage/${guildId}/tickets`);
}
async function sendMessage(e) {
let data = {
message: e.detail,
};
const res = await axios.post(`${API_URL}/api/${guildId}/tickets/${ticketId}`, data);
if (res.status !== 200) {
if (res.status === 429) {
notifyRatelimit();
} else {
notifyError(res.data.error);
}
}
}
function connectWebsocket() {
const ws = new WebSocket(`${WS_URL}/webchat`);
ws.onopen = () => {
ws.send(JSON.stringify({
"type": "auth",
"data": {
"guild_id": guildId,
"ticket_id": ticketId,
"token": getToken(),
}
}));
};
ws.onmessage = (evt) => {
const data = JSON.parse(evt.data);
messages = [...messages, data];
scrollContainer();
};
}
async function loadMessages() {
const res = await axios.get(`${API_URL}/api/${guildId}/tickets/${ticketId}`);
if (res.status !== 200) {
notifyError(res.data.error);
return;
}
messages = res.data.messages;
}
async function loadPremium() {
const res = await axios.get(`${API_URL}/api/${guildId}/premium?include_voting=true`);
if (res.status !== 200) {
notifyError(res.data.error);
return;
}
isPremium = res.data.premium;
}
withLoadingScreen(async () => {
setDefaultHeaders();
await Promise.all([
loadPremium(),
loadMessages()
]);
scrollContainer();
if (isPremium) {
connectWebsocket();
}
});
</script>
<style>
.parent {
display: flex;
justify-content: center;
width: 100%;
height: 100%;
}
.content {
display: flex;
justify-content: space-between;
width: 96%;
height: 100%;
margin-top: 30px;
}
.body-wrapper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
padding: 1%;
}
.section {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.section:not(:first-child) {
margin-top: 2%;
}
.section-title {
font-size: 36px;
font-weight: bolder !important;
}
h3 {
font-size: 28px;
margin-bottom: 4px;
}
.row {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
}
@media only screen and (max-width: 576px) {
.row {
flex-direction: column;
}
}
</style>