add feedback and report things
This commit is contained in:
66
src/pages/feedback/[urlHash].astro
Normal file
66
src/pages/feedback/[urlHash].astro
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
import WebsiteLayout from '@layouts/website/WebsiteLayout.astro';
|
||||
import Input from '@components/input/Input.svelte';
|
||||
import Textarea from '@components/input/Textarea.svelte';
|
||||
import { db } from '@db/database.ts';
|
||||
|
||||
const { urlHash } = Astro.params;
|
||||
|
||||
const feedback = urlHash ? await db.getFeedbackByUrlHash({ urlHash: urlHash }) : null;
|
||||
|
||||
if (!feedback) {
|
||||
return new Response(null, { status: 404 });
|
||||
}
|
||||
---
|
||||
|
||||
<WebsiteLayout title="Feedback">
|
||||
<div class="flex justify-center items-center">
|
||||
<div class="mt-12 grid card w-11/12 xl:w-2/3 2xl:w-1/2 p-6 shadow-lg">
|
||||
<h2 class="text-3xl text-center">Feedback</h2>
|
||||
<form id="feedback" data-url-hash={urlHash}>
|
||||
<div class="space-y-4 mt-6 mb-4">
|
||||
<Input value={feedback.title} label="Event" dynamicWidth readonly />
|
||||
<Textarea
|
||||
id="content"
|
||||
value={feedback.content}
|
||||
label="Feedback"
|
||||
rows={10}
|
||||
dynamicWidth
|
||||
required
|
||||
readonly={feedback.content !== null}
|
||||
/>
|
||||
</div>
|
||||
<button id="send" class="btn" disabled>Feedback senden</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</WebsiteLayout>
|
||||
|
||||
<script>
|
||||
import { actions } from 'astro:actions';
|
||||
import { actionErrorPopup } from '@util/action';
|
||||
|
||||
document.addEventListener('astro:page-load', () => {
|
||||
const form = document.getElementById('feedback') as HTMLFormElement;
|
||||
const content = document.getElementById('content') as HTMLTextAreaElement;
|
||||
const sendButton = document.getElementById('send') as HTMLButtonElement;
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const { error } = await actions.feedback.submitFeedback({
|
||||
urlHash: form.dataset.urlHash!,
|
||||
content: content.value
|
||||
});
|
||||
|
||||
if (error) {
|
||||
actionErrorPopup(error);
|
||||
return;
|
||||
}
|
||||
|
||||
content.readOnly = true;
|
||||
sendButton.disabled = true;
|
||||
});
|
||||
content.addEventListener('input', () => (sendButton.disabled = content.value === '' || content.readOnly));
|
||||
});
|
||||
</script>
|
||||
23
src/pages/report/[urlHash].astro
Normal file
23
src/pages/report/[urlHash].astro
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
import WebsiteLayout from '@layouts/website/WebsiteLayout.astro';
|
||||
import { db } from '@db/database.ts';
|
||||
import Draft from './_draft.astro';
|
||||
import Submitted from './_submitted.astro';
|
||||
import Popup from '@components/popup/Popup.svelte';
|
||||
import ConfirmPopup from '@components/popup/ConfirmPopup.svelte';
|
||||
|
||||
const { urlHash } = Astro.params;
|
||||
|
||||
const report = urlHash ? await db.getReportByUrlHash({ urlHash: urlHash }) : null;
|
||||
|
||||
if (!report) {
|
||||
return new Response(null, { status: 404 });
|
||||
}
|
||||
---
|
||||
|
||||
<WebsiteLayout title="Report">
|
||||
{report.createdAt === null ? <Draft report={report} /> : <Submitted report={report} />}
|
||||
</WebsiteLayout>
|
||||
|
||||
<Popup client:idle />
|
||||
<ConfirmPopup client:idle />
|
||||
105
src/pages/report/_draft.astro
Normal file
105
src/pages/report/_draft.astro
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
import type { db } from '@db/database.ts';
|
||||
import AdversarySearch from '@app/website/report/AdversarySearch.svelte';
|
||||
import Dropzone from '@app/website/report/Dropzone.svelte';
|
||||
import Input from '@components/input/Input.svelte';
|
||||
import Textarea from '@components/input/Textarea.svelte';
|
||||
import { MAX_UPLOAD_BYTES } from 'astro:env/server';
|
||||
|
||||
interface Props {
|
||||
report: Awaited<ReturnType<db.getReportByUrlHash>>;
|
||||
}
|
||||
|
||||
const { report } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="flex justify-center items-center">
|
||||
<div class="mt-12 grid card w-11/12 xl:w-2/3 2xl:w-1/2 p-6 shadow-lg">
|
||||
<h2 class="text-3xl text-center">
|
||||
Report von Team <span class="underline">A</span> gegen Team <span id="adversary-team-name" class="underline"
|
||||
>B</span
|
||||
>
|
||||
</h2>
|
||||
<form id="report" data-url-hash={report.urlHash} data-adversary-team={report.reported?.name}>
|
||||
<div class="space-y-4 my-4">
|
||||
<div class="flex flex-col gap-4">
|
||||
<AdversarySearch
|
||||
adversary={{ type: report.reported ? 'team' : 'unknown', name: report.reported?.name }}
|
||||
client:load
|
||||
/>
|
||||
<Input id="reason" value={report.reason} label="Report Grund" dynamicWidth />
|
||||
<Textarea id="body" value={report.body} label="Details" rows={10} dynamicWidth required />
|
||||
<Dropzone maxFilesBytes={MAX_UPLOAD_BYTES} client:load />
|
||||
</div>
|
||||
<button id="send" class="btn" disabled={report.body}>Report senden</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { actions } from 'astro:actions';
|
||||
import { actionErrorPopup } from '@util/action';
|
||||
import { popupState } from '@components/popup/Popup';
|
||||
|
||||
document.addEventListener('astro:page-load', () => {
|
||||
const eventCancelController = new AbortController();
|
||||
document.addEventListener('astro:after-swap', () => eventCancelController.abort());
|
||||
|
||||
const adversary = document.getElementById('adversary-team-name') as HTMLSpanElement;
|
||||
const form = document.getElementById('report') as HTMLFormElement;
|
||||
const reason = document.getElementById('reason') as HTMLInputElement;
|
||||
const body = document.getElementById('body') as HTMLTextAreaElement;
|
||||
const sendButton = document.getElementById('send') as HTMLButtonElement;
|
||||
|
||||
let attachments: File[] = [];
|
||||
|
||||
body.addEventListener('change', () => {
|
||||
sendButton.disabled = !body.value;
|
||||
});
|
||||
|
||||
document.addEventListener(
|
||||
'adversaryInput',
|
||||
(e: any & { detail: { adversaryTeamName: string } }) => {
|
||||
adversary.textContent = e.detail.adversaryTeamName;
|
||||
},
|
||||
{ signal: eventCancelController.signal }
|
||||
);
|
||||
document.addEventListener(
|
||||
'dropzoneInput',
|
||||
(e: any & { detail: { files: File[] } }) => {
|
||||
attachments = e.detail.files;
|
||||
},
|
||||
{ signal: eventCancelController.signal }
|
||||
);
|
||||
|
||||
form.addEventListener(
|
||||
'submit',
|
||||
async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData();
|
||||
formData.set('urlHash', form.dataset.urlHash!);
|
||||
formData.set('reason', reason.value);
|
||||
formData.set('body', body.value);
|
||||
for (const attachment of attachments) {
|
||||
formData.append('files', attachment);
|
||||
}
|
||||
|
||||
const { error } = await actions.report.submitReport(formData);
|
||||
if (error) {
|
||||
actionErrorPopup(error);
|
||||
return;
|
||||
}
|
||||
|
||||
popupState.set({
|
||||
type: 'info',
|
||||
title: 'Report abgeschickt',
|
||||
message: 'Der Report wurde abgeschickt. Ein Admin wird sich schnellstmöglich darum kümmern.',
|
||||
onClose: () => location.reload()
|
||||
});
|
||||
},
|
||||
{ signal: eventCancelController.signal }
|
||||
);
|
||||
});
|
||||
</script>
|
||||
33
src/pages/report/_submitted.astro
Normal file
33
src/pages/report/_submitted.astro
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
import type { db } from '@db/database.ts';
|
||||
import Textarea from '@components/input/Textarea.svelte';
|
||||
|
||||
interface Props {
|
||||
report: Awaited<ReturnType<db.getReportByUrlHash>>;
|
||||
}
|
||||
|
||||
const { report } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="flex justify-center items-center">
|
||||
<div class="mt-12 grid card w-11/12 xl:w-2/3 2xl:w-1/2 p-6 shadow-lg">
|
||||
{
|
||||
report.status.status === null ? (
|
||||
<p>Dein Report wird in kürze bearbeitet</p>
|
||||
) : report.status.status === 'open' ? (
|
||||
<p>Dein Report befindet sich in Bearbeitung</p>
|
||||
) : (
|
||||
<>
|
||||
<p>Dein Report wurde bearbeitet</p>
|
||||
<Textarea
|
||||
value={report.status.statement}
|
||||
label="Antwort vom Admin Team (optional)"
|
||||
rows={5}
|
||||
dynamicWidth
|
||||
readonly
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user