diff --git a/src/components/PatchNote.jsx b/src/components/PatchNote.jsx
new file mode 100644
index 0000000..3878bcc
--- /dev/null
+++ b/src/components/PatchNote.jsx
@@ -0,0 +1,45 @@
+import { MarkdownViewer } from '@/components/MarkdownViewer';
+import React from 'react';
+import { useState } from 'react';
+
+export function PatchNote({description, date, title, version}) {
+ const [dropDown, setDropDown] = useState(false);
+ const [readMoreBtn, setReadMoreBtn] = useState(false);
+
+
+ return (
+ <>
+
+
setDropDown(!(dropDown) )
+ }>
+
+
+
+ {version}
+ {title}
+
+
+
+
{date}
+
+
+
+
+ {!dropDown ?
+
+
+ {description.length>190 && (
+
+ )
+ }
+
+
:
+ }
+
+
+
+
+ >
+ );
+}
diff --git a/src/pages/moderation.jsx b/src/pages/moderation.jsx
index 34abc99..d0d92a7 100644
--- a/src/pages/moderation.jsx
+++ b/src/pages/moderation.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import {
ArrowRightIcon,
QuestionMarkCircleIcon,
@@ -13,20 +13,40 @@ import request from '@/utils/request';
import { MyTable } from '@/components/Table';
import { TableHead, TableRow, TableHeader, TableCell, TableBody, Table } from "@/components/ui/table"
import ViewChallenge from '@/components/moderation/ViewChallenge';
+import { MarkdownViewer } from '@/components/MarkdownViewer';
+
+
export default function Competitions() {
const [selectedChallenges, setSelectedChallenges] = useState([]);
const [selectedId, setSelectedId] = useState(null);
const [pendingChallenges, setPendingChallenges] = useState([]);
const [challengeIsOpen, setChallengeIsOpen] = useState(false);
-
+ const [contentPreview, setContentPreview] = useState('');
+ const textRef = useRef(null);
const [reports, setReports] = useState([]);
const [bonusPoints, setBonusPoints] = useState(0);
-
+ const insertText = (text) => {
+ const textarea = textRef.current;
+ const startPos = textarea.selectionStart;
+ const endPos = textarea.selectionEnd;
+ const newValue =
+ textarea.value.substring(0, startPos) +
+ text +
+ textarea.value.substring(endPos, textarea.value.length);
+ setContentPreview(newValue);
+ textarea.focus();
+ textarea.selectionEnd = startPos + text.length;
+ };
+ const magicSnippet = () => {
+ const id = Math.random().toString(36).substring(7);
+ insertText(`[Click to run: ${id}](https://ctfguide.com/magic/)`);
+ };
+
// get reports
useEffect(() => {
const fetchReports = async () => {
@@ -157,6 +177,31 @@ export default function Competitions() {
}
};
+ const handleUploadPatchnote = async () => {
+ const title = document.getElementById('titleInput').value;
+ const version = document.getElementById('versionInput').value;
+ const content = document.getElementById('content').value;
+ const author = "CTFGuide";
+
+ if (!title || !version || !content) {
+ alert("Please fill in all fields.");
+ return;
+ }
+
+ try{
+ const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/createPatchNote`, "POST", {title, version, content});
+ if(response.success){
+ alert("Patchnote uploaded successfully!");
+ }else {
+ alert("Failed to upload the patchnote.");
+ }
+
+ }catch(err){
+ console.log(err);
+ alert("An error occurred while uploading the patchnote.");
+ }
+ };
+
return (
<>
@@ -261,9 +306,90 @@ export default function Competitions() {
+
+
+
+
+
+ Create a Patchnote
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Patchnote Content Preview
+
+
+
+
+
+
+
+
diff --git a/src/pages/patch-notes.jsx b/src/pages/patch-notes.jsx
new file mode 100644
index 0000000..b62e024
--- /dev/null
+++ b/src/pages/patch-notes.jsx
@@ -0,0 +1,70 @@
+import Head from 'next/head';
+import { Footer } from '@/components/Footer';
+import { StandardNav } from '@/components/StandardNav';
+import { useEffect, useState } from 'react';
+import {PatchNote} from '@/components/PatchNote';
+import request from '@/utils/request';
+
+export default function PatchNotes() {
+ const[patchNotes, setPatchNotes] = useState([{
+ description: "Description of the patch note",
+ date: "8/4/2024",
+ title: "CTFGuide Release",
+ version: "Version 1.0.0"
+ },{
+ description: "# ALLAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx `sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss`",
+ date: "8/4/2024",
+ title: "CTFGuide Release",
+ version: "Version 1.0.0"
+ }]);
+
+ async function getPatchNotes() {
+ //fetch patch notes
+ const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/patchNotes`, 'GET', null);
+ if(!response.error) {
+ setPatchNotes(response);
+ }
+ }
+
+ useEffect(() => {
+ getPatchNotes();
+ }, []);
+
+ console.log('patchNotes:', patchNotes);
+
+return (
+ <>
+
+ Patch Notes - CTFGuide
+
+
+
+
+
+
+
+ Patch Notes
+
+
+ A changelog of updates to the CTFGuide platform
+
+ {patchNotes &&
+ patchNotes.map((patchNote) => {
+ return (
+
+ );
+ })
+ }
+
+
+
+
+ >
+);
+}