initial commit

This commit is contained in:
Soph :3 2024-05-22 11:35:43 +03:00
commit 6f5a39c212
Signed by: sophie
GPG key ID: EDA5D222A0C270F2
47 changed files with 3601 additions and 0 deletions

View file

@ -0,0 +1,188 @@
import { useEffect, useRef, useState } from "preact/hooks";
import toast from 'react-hot-toast';
import { useGoogleReCaptcha } from "react-google-recaptcha-v3";
import Button from "../../miniComponents/Button";
import Input from "../../miniComponents/Input";
import { trty } from "../../treaty";
export default function SidebarAccount({ setSocketUrl, currentView, accountState, setAccountState }) {
const rerun = useState<boolean>(false);
useEffect(() => {
async function asyncFunc() {
const data = (await trty.api.auth.userInfo.get()).data;
if (data) {
setAccountState(data as { username: string })
} else {
setAccountState(undefined)
}
}
asyncFunc()
}, [rerun])
function AccountSignedIn() {
const statusRef = useRef<HTMLInputElement>();
async function handleLogout() {
await trty.api.auth.logout.get();
rerun[1](a => !a)
}
async function uploadImage() {
let image_input = document.getElementById("profile_picture_input") as HTMLInputElement
if (!image_input) {
image_input = document.createElement("input");
image_input.style.display = "none";
image_input.type = "file"
image_input.accept = "image/jpeg, image/png, image/jpg"
image_input.id = "profile_picture_input"
document.body.appendChild(image_input)
image_input.addEventListener("change", () => {
toast.promise((async () => {
await trty.api.profile.setProfilePicture.post({
file: image_input.files[0]
})
})(), {
loading: "Uploading..",
success: "Uploaded!",
error: "Upload failed. :("
})
})
}
image_input.click()
}
return (
<>
<div class="flex flex-col">
<h1 class="text-center text-xl text-white ">Signed in as <strong>{accountState.username}</strong></h1>
<Button onClick={handleLogout}>Logout</Button>
<Button onClick={uploadImage}>
<div class="flex items-center text-center">
<i class="fa-solid fa-image text-3xl text-slate-500 mr-2"></i>Set a profile picture
</div>
</Button>
<Input placeholder="Set a status!" ref={statusRef}></Input>
<Button onClick={() => {
toast.promise((async () => {
if(statusRef.current.value.trim()) {
await trty.api.profile.setStatus.post({
status: statusRef.current.value
});
}
})(), {
success: "Status set!",
loading: "Setting status..",
error: "Failed to set status."
})
}}>Set status</Button>
</div>
</>
)
}
function AccountSignedOut() {
const usernameRef = useRef<HTMLInputElement>();
const passwordRef = useRef<HTMLInputElement>();
const { executeRecaptcha } = useGoogleReCaptcha();
async function handleSignIn() {
const username = usernameRef.current.value.trim();
const password = passwordRef.current.value.trim();
if (!username || !password) {
toast.error("Missing username or password!", {
position: "bottom-right",
})
return;
}
const loadingToast = toast.loading("Logging in..", {
position: "bottom-right",
});
const token = await executeRecaptcha("login");
const request = await trty.api.auth.login.post({
password: password,
username: username,
recaptcha: token
})
if (request.status != 200) {
toast.error(request.error.value as unknown as string, {
position: "bottom-right",
});
toast.remove(loadingToast);
return;
}
toast.success(`You've logged into ${username}!`, {
position: "bottom-right",
})
toast.remove(loadingToast);
setSocketUrl(z => z.replace(/\?.*$/gm, "") + "?a=" + Math.random())
rerun[1](a => !a)
}
async function handleRegister() {
const username = usernameRef.current.value.trim();
const password = passwordRef.current.value.trim();
if (!username || !password) {
toast.error("Missing username or password!", {
position: "bottom-right",
})
return;
}
const loadingToast = toast.loading("Registering..", {
position: "bottom-right",
});
const token = await executeRecaptcha("register");
const request = await trty.api.auth.register.post({
password: password,
username: username,
recaptcha: token
})
if (request.status != 200) {
toast.error(request.error.value as unknown as string, {
position: "bottom-right",
});
toast.remove(loadingToast);
return;
}
toast.success(`Your account ${username} has been registered!`, {
position: "bottom-right",
})
toast.remove(loadingToast);
}
return (
<>
<div class="flex flex-col">
<Input placeholder="Username" extraClass="mb-1" type="username" ref={usernameRef}></Input>
<Input placeholder="Password" extraClass="mb-1" type="password" ref={passwordRef}></Input>
<Button onClick={handleSignIn}>Sign In</Button>
<Button onClick={handleRegister}>Register</Button>
<div class="text-sm m-2">
This site is protected by reCAPTCHA and the Google <a class="text-gray-400" href="https://policies.google.com/privacy">Privacy Policy</a> and <a href="https://policies.google.com/terms" class="text-gray-400">Terms of Service</a> apply.
</div>
</div>
</>
)
}
return (
<>
<h1 class="text-center text-3xl text-white ">Account</h1>
{
(() => {
if (!accountState) {
return <AccountSignedOut></AccountSignedOut>
} else {
return <AccountSignedIn></AccountSignedIn>
}
})()
}
</>
)
}

View file

@ -0,0 +1,60 @@
import { useRef } from "preact/hooks";
import Button from "../../miniComponents/Button";
import Input from "../../miniComponents/Input";
export default function SidebarRooms({ setSendRoomHidden, setRoomName, roomName, currentView, rooms }) {
const dialogRef = useRef<HTMLDialogElement>();
const roomInputRef = useRef<HTMLInputElement>();
const roomIsHiddenRef = useRef<HTMLInputElement>();
function createRoomDialog() {
dialogRef.current.showModal();
}
function createRoom() {
const input = roomInputRef.current.value.trim();
if (input) {
setSendRoomHidden(roomIsHiddenRef.current.checked);
localStorage.lastRoom = input;
setRoomName(input);
dialogRef.current.close();
}
}
return (
<>
<dialog ref={dialogRef} class="bg-slate-400 p-5 rounded-xl">
<div class="flex flex-col">
<Input ref={roomInputRef} placeholder="My Awsome Room"></Input>
<div class="text-center text-white my-2">
<Input type="checkbox" extraClasses="mr-2" ref={roomIsHiddenRef}></Input>
Is room hidden?
</div>
<Button onClick={createRoom}>Create room</Button>
</div>
</dialog>
<h1 class="text-center text-3xl text-white ">Rooms</h1>
<div class="flex flex-col">
{
rooms ?
rooms.map(z => {
return <Button onClick={
() => {
setSendRoomHidden(false);
setRoomName(z.name)
}
} extraClass={roomName == z.name ? "bg-green-200" : "bg-slate-400"}>
<div class="text-2xl">{z.name}</div>
<div>{z.count} pe{z.count == 1 ? "rson" : "ople"}</div>
</Button>
}) : <h1 class="text-2xl text-black text-center">Loading..</h1>
}
<Button onClick={createRoomDialog}>
Create your own room
</Button>
</div>
</>
)
}

View file

@ -0,0 +1,63 @@
import { useRef, useState } from "preact/hooks";
import toast from 'react-hot-toast';
import Button from "../../miniComponents/Button";
import Input from "../../miniComponents/Input";
import { trty } from "../../treaty";
export default function SidebarStaff({ setCurrentPeopleView, currentView, setUser }) {
const userIdRef = useRef<HTMLInputElement>();
const [punishments, setPunishments] = useState<undefined | any[]>();
return (
<>
<h1 class="text-center text-3xl text-white">Staff</h1>
<div class="border-b-4">
<Input placeholder="user ID" extraClass="m-0" ref={userIdRef}></Input>
<Button extraClass="m-0 py-2 my-2 w-full" onClick={async () => {
const req = await trty.api.staff.punishments.post({
userId: userIdRef.current.value
})
if (req.data) setPunishments(req.data as any);
}}>See punishments</Button>
<Button extraClass="m-0 py-2 mb-2 w-full" onClick={() => {
const bar = document.getElementById("peopleBar");
const barButton = document.getElementById("peopleBarButton");
if (bar.style.display !== "flex") {
bar.style.display = "flex";
barButton.className = barButton.className.replace('right-6', "right-64")
}
setCurrentPeopleView("person");
setUser({ id: userIdRef.current.value });
}}>User actions</Button>
</div>
{punishments === undefined ? "No user searched." : punishments.length == 0 ? "This user has no punishments!" : punishments.map((z, i) => {
return <div class={(i == 0 ? "" : "border-t-2") + " text-black"}>
<Button extraClass="p-2 m-1" onClick={() => {
toast.promise((async () => {
await trty.api.staff.invalidatePunishment.post({
punishmentId: z.id
})
})(), {
loading: "Invalidating punishment..",
success: "Invalidated.",
error: "Failed to invalidate!"
})
}}>Remove punishment</Button>
<div><i class={"text-white fa-solid fa-" + (z.type == "ban" ? "hammer-crash" : "comment-slash")}></i> {z.type.toUpperCase()}</div>
<div>ID: <strong>{z.id}</strong></div>
<div>Reason: <strong>{z.reason}</strong></div>
<div>Banned by: <strong>{z.staffId}</strong></div>
<div>Time: <strong>{z.time}ms</strong></div>
<div>Banned at: <strong>{z.at.toString()}</strong></div>
</div>
})}
</>
)
}