diff options
Diffstat (limited to 'front/src/routes/bots.jsx')
-rw-r--r-- | front/src/routes/bots.jsx | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/front/src/routes/bots.jsx b/front/src/routes/bots.jsx new file mode 100644 index 0000000..c2f1565 --- /dev/null +++ b/front/src/routes/bots.jsx @@ -0,0 +1,194 @@ +import Modal from "react-modal"; +import { useAuthContext } from "../context/auth_context"; +import { useEffect, useState } from "react"; + +Modal.setAppElement("#root"); + +const BotButton = ({ onSave, givenBot }) => { + const [open, setOpen] = useState(false); + const [name, setName] = useState(givenBot?.name || ""); + const [webhook, setWebhook] = useState(givenBot?.webhook || ""); + const [errors, setErrors] = useState(null); + const [isPublic, setIsPublic] = useState(givenBot?.public || false); + + const setDefaults = () => { + setName(""); + setWebhook(""); + setErrors(null); + }; + + const close = () => { + if (!givenBot) { + setDefaults(); + } + setOpen(false); + }; + + const updateBot = () => { + fetch(givenBot ? `/api/player/bots/${givenBot.id}` : "/api/player/bots", { + credentials: "same-origin", + method: givenBot ? "PUT" : "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + webhook: webhook.trim(), + name: name.trim(), + public: isPublic, + }), + }) + .then((r) => r.json()) + .then((d) => { + if (d.success) { + if (onSave) { + onSave(); + } + close(); + } else if (d.errors) { + if (typeof d.errors === "object") { + setErrors( + Object.keys(d.errors).map( + (field) => `${field}: ${d.errors[field].join(",")}` + ) + ); + } else { + setErrors([d.errors]); + } + } + }); + }; + + return ( + <div> + <button className="button" onClick={() => setOpen(true)}> + {givenBot ? "Update" : "+ Add"} Bot + </button> + {givenBot && ( + <> + <button + style={{ marginLeft: "1rem" }} + className="button gold" + onClick={() => { + navigator.clipboard.writeText(givenBot?.token); + alert("Bot's token was copied to the clipboard."); + }} + > + Copy Token + </button> + <button + style={{ marginLeft: "1rem" }} + className="button red" + onClick={() => + fetch(`/api/player/bots/${givenBot.id}/redrive`) + .then((r) => r.json()) + .then(({ message }) => alert(message)) + } + > + Schedule Redrive + </button> + </> + )} + <Modal + isOpen={open} + onRequestClose={close} + className="modal" + contentLabel="Add Bot" + > + <div style={{ minWidth: "20vw" }}> + <h3>Add Bot</h3> + <hr /> + <p>Bot Name *</p> + <input + style={{ width: "100%" }} + value={name} + onChange={(e) => setName(e.target.value)} + required + /> + </div> + <div> + <p>Webhook *</p> + <input + style={{ width: "100%" }} + value={webhook} + onChange={(e) => setWebhook(e.target.value)} + required + /> + </div> + <p> + Public *{" "} + <input + type="checkbox" + value={name} + checked={isPublic} + onChange={(e) => setIsPublic(!isPublic)} + required + /> + </p> + <div> + {errors && ( + <div style={{ color: "red" }}> + {errors.map((error, i) => ( + <p key={i}>{error}</p> + ))} + </div> + )} + </div> + <div className="flex-end-row"> + <button className="button" onClick={updateBot}> + {givenBot ? "Update" : "+ Add"} + </button> + <button className="button red" onClick={close}> + Cancel + </button> + </div> + </Modal> + </div> + ); +}; + +export const BotCard = ({ botStruct, onSave }) => { + const { name } = botStruct; + return ( + <div className="key-card"> + <h4>{name}</h4> + <BotButton onSave={onSave} givenBot={botStruct} /> + </div> + ); +}; + +export const Bots = () => { + const { + player: { id: userId }, + } = useAuthContext(); + const [bots, setBots] = useState(null); + + const refreshBots = () => + fetch("/api/player/bots") + .then((r) => r.json()) + .then((bots) => setBots(bots)); + + useEffect(() => { + if (userId) { + refreshBots(); + } + }, [userId]); + + if (bots === null) return <p>Loading...</p>; + + return ( + <> + <h1>Bots</h1> + <BotButton onSave={refreshBots} /> + + <div className="key-card-collection"> + {bots.length ? ( + bots.map((bot) => ( + <BotCard key={bot.id} onSave={refreshBots} botStruct={bot} /> + )) + ) : ( + <p>Looks like you've got no bots, try adding one!</p> + )} + </div> + </> + ); +}; |