Forgot to add a file like normal
diff --git a/Components/overlays/christmas.js b/Components/overlays/christmas.js
new file mode 100644
index 0000000..dc2283e
--- /dev/null
+++ b/Components/overlays/christmas.js
@@ -0,0 +1,17 @@
+import React from "react";
+import Snowfall from 'react-snowfall'
+
+React.useLayoutEffect = React.useEffect
+
+function Christmas({ }) {
+ return (
+ <div style={{width: "100%", height: "100%"}}>
+ <Snowfall
+ snowflakeCount={100}
+ color="#C4C4C4AA"
+ />
+ </div>
+ )
+}
+
+export default Christmas;
diff --git a/embed/index.js b/embed/index.js
new file mode 100644
index 0000000..7ef2ced
--- /dev/null
+++ b/embed/index.js
@@ -0,0 +1,106 @@
+import HCaptcha from 'react-hcaptcha';
+import Axios from 'axios';
+import Router from 'next/router';
+import React from 'react';
+import Header from '../../../Components/Header'
+import { useReward } from 'react-rewards';
+import { Card, CardRow } from '../../../Components/Card';
+
+import { AutoLayout, Panel, Title, Text, Divider } from '../../../Components/Panels';
+import { List, ListItem } from '../../../Components/Texttools';
+import { useColorMode } from 'theme-ui';
+import Styles from '../../../styles/nucleus/embed.module.css';
+
+
+function Embed(props) {
+ const [clicked, setClicked] = React.useState(false);
+ const [theme, setTheme] = useColorMode()
+
+ const { reward: reward, isAnimating: isAnimating } = useReward('confetti', 'confetti', {
+ elementSize: 10,
+ elementCount: 150,
+ startVelocity: 35,
+ lifetime: 300,
+ decay: 0.94,
+ spread: 170,
+ position: "absolute",
+ colors: ["#68D49E"]
+ });
+
+ async function submitForm(tkn) {
+ if ( clicked ) {
+ Router.push('/nucleus/verify/alreadyVerified', '/nucleus/verify/success');
+ }
+ setClicked(true);
+ reward();
+ let code = await Axios.post('/api/nucleus/verify/complete', {
+ code: props.code,
+ tkn: tkn
+ });
+ setTimeout(() => {
+ if (code.data.success === true ) return Router.push('/nucleus/verify/success','/nucleus/verify')
+ else return Router.push('/nucleus/verify/failure','/nucleus/verify')
+ }, 2500);
+ }
+
+ return <>
+ <Header
+ name="Embed Editor"
+ subtext={`Editing embed in ${props.gName}`}
+ gradient={["F27878", "D96B6B"]}
+ wave="web/waves/header/nucleus"
+ buttons={[]}
+ />
+ <AutoLayout>
+ <Panel>
+ <Title>Preview</Title>
+ <Divider name="preview"/>
+ <div className={Styles.previewEmbed}>
+ <div className={Styles.left}></div>
+ <div className={Styles.title}><input ></input></div>
+ <div className={Styles.description}><input ></input></div>
+ </div>
+ <div className={Styles.right}>
+ <div className={Styles.uploadImage} />
+ </div>
+ <>
+
+ </>
+ <div className={Styles.footer}>
+ <ImageUpload size={64} />
+ </div>
+ </Panel>
+ <Panel halfSize={false} id="invite">
+ <Title>Invite</Title>
+ <Divider />
+ <CardRow>
+ <Card
+ wave="nucleus"
+ icon="bots/nucleus/circle"
+ buttonText={"FFFFFF"} gradient={["F27878", "D96B6B"]}
+ title="Nucleus"
+ subtext="Invite Nucleus to your server"
+ buttons={[
+ {color: "424242", link: "https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands", text: "Invite"}
+ ]}
+ url="https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands"
+ />
+ </CardRow>
+ </Panel>
+ </AutoLayout>
+ </>
+}
+
+export default Embed;
+export async function getServerSideProps(ctx) {
+ return {
+ props: {
+ gID: code.data.gID,
+ gName: code.data.gName,
+ mID: code.data.mID,
+ cID: code.data.cID,
+ headers: headers,
+ code: ctx.query.code
+ }
+ }
+}
\ No newline at end of file
diff --git a/pages/api/season.js b/pages/api/season.js
new file mode 100644
index 0000000..87d650d
--- /dev/null
+++ b/pages/api/season.js
@@ -0,0 +1,32 @@
+function getSeason() {
+ let year = new Date().getFullYear();
+
+ const dates = {
+ pride: [new Date(`${year}-6-1`), new Date(`${year}-6-31`)],
+ halloween: [new Date(`${year}-10-25`), new Date(`${year}-11-1`)],
+ trans: [new Date(`${year}-11-13`), new Date(`${year}-11-19`)],
+ christmas: [new Date(`${year}-12-1`), new Date(`${year}-12-26`)]
+ }
+ const filePaths = {
+ normal: "normal",
+ halloween: "seasonal/halloween",
+ christmas: "seasonal/christmas",
+ pride: "seasonal/pride",
+ trans: "seasonal/trans"
+ }
+
+ let current = new Date();
+ let currentSeason = Object.keys(dates).find((str) => current >= dates[str][0] && current <= dates[str][1]) || "normal";
+
+ return {
+ season: currentSeason,
+ filePath: filePaths[currentSeason]
+ }
+}
+
+const Season = async (req, res) => {
+ return res.status(200).send(getSeason());
+}
+
+export default Season;
+export { getSeason };
diff --git a/styles/nucleus/rolemenu.module.css b/styles/nucleus/rolemenu.module.css
new file mode 100644
index 0000000..174a5ae
--- /dev/null
+++ b/styles/nucleus/rolemenu.module.css
@@ -0,0 +1,32 @@
+.optionBox {
+ display: flex;
+ flex-direction: row;
+ justify-content: left;
+ align-items: center;
+ width: 100%;
+}
+
+/* .optionBox input {
+ position: absolute;
+ opacity: 0;
+ height: 0;
+ width: 0;
+} */
+
+.options {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ justify-content: left;
+ align-items: center;
+ width: fit-content;
+ height: 100%;
+}
+
+/* .option {
+ height: 20px;
+ width: 20px;
+ position: absolute;
+ border: solid 5px red !important;
+ background-color: blue;
+} */
\ No newline at end of file
diff --git a/todo/rolemenu/index.js b/todo/rolemenu/index.js
new file mode 100644
index 0000000..a057f9f
--- /dev/null
+++ b/todo/rolemenu/index.js
@@ -0,0 +1,131 @@
+import Axios from 'axios';
+import Router from 'next/router';
+import React from 'react';
+import Header from '../../Components/Header'
+import { useReward } from 'react-rewards';
+
+import { AutoLayout, Panel, Title, Text, Divider } from '../../Components/Panels';
+import { useColorMode } from 'theme-ui';
+import Styles from '../../../styles/nucleus/rolemenu.module.css';
+
+function RoleMenu(props) {
+ const [clicked, setClicked] = React.useState(false);
+ const [formState, setFormState] = React.useState({});
+ const [theme, setTheme] = useColorMode()
+
+ const { reward: reward, isAnimating: isAnimating } = useReward('confetti', 'confetti', {
+ elementSize: 10,
+ elementCount: 150,
+ startVelocity: 35,
+ lifetime: 300,
+ decay: 0.94,
+ spread: 170,
+ position: "absolute",
+ colors: ["#68D49E"]
+ });
+
+ function handleChange(event) {
+ const { name, value } = event.target;
+ setFormState({ ...formState, [name]: value });
+ }
+
+ async function submitForm() {
+ if (!isAnimating) reward();
+ return
+ let code = await Axios.post('/api/nucleus/rolemenu/complete', {
+ code: props.code
+ });
+ setTimeout(() => {
+ if (code.data.success === true ) return Router.push('/nucleus/rolemenu/success','/nucleus/rolemenu')
+ else return Router.push('/nucleus/rolemenu/failure','/nucleus/rolemenu')
+ }, 2500);
+ }
+
+ return <>
+ <Header
+ name={props.guildName}
+ customImage={props.guildIcon}
+ roundImage={true}
+ subtext={`Welcome, ${props.username}`}
+ gradient={["F27878", "D96B6B"]}
+ wave="web/waves/header/nucleus"
+ buttons={[]}
+ />
+ <form onSubmit={submitForm}>
+ <AutoLayout>
+ {props.data.map((item, index) => {
+ return <Panel key={index} halfSize={true}>
+ <Title>{item.name}</Title>
+ <Divider/>
+ <Text>{item.description}</Text>
+ <div className={Styles.options}>
+ {
+ item.options.map((props, optionIndex) => {return <div className={Styles.optionBox}>
+ <input
+ type={item.max === 1 ? "radio" : "checkbox"}
+ style={{borderRadius: item.max === 1 ? "50%" : "5px"}}
+ className={Styles.option}
+ key={item.name + optionIndex}
+ id={item.name + optionIndex.toString()}
+ name={item.name}
+ value={props.name}
+ onChange={handleChange}
+ />
+ <label htmlFor={item.name + optionIndex.toString()}>{props.name}</label>
+ </div>})
+ }
+ </div>
+ </Panel>
+ })}
+ <Panel halfSize={false}>
+ <Title>Save</Title>
+ <Divider/>
+ <Text>
+ After selecting all your roles, click the button below to save your choices.
+ </Text>
+ <div id="confetti" />
+ <div className={Styles.submit}>
+ <button type="submit" disabled={isAnimating}>
+ {isAnimating ? "Saving..." : "Save"}
+ </button>
+ </div>
+ </Panel>
+ </AutoLayout>
+ </form>
+ </>
+}
+
+export default RoleMenu;
+export async function getServerSideProps(ctx) {
+ if(!ctx.query.code) {
+ return {
+ redirect: {
+ destination: '/nucleus',
+ permanent: true
+ }
+ }
+ }
+ let code;
+ try {
+ code = (await Axios.get(`http://localhost:10000/rolemenu/${ctx.query.code}`)).data;
+ } catch (e) {
+ return {
+ redirect: {
+ destination: '/nucleus/rolemenu/failure',
+ permanent: true
+ }
+ }
+ }
+ let headers = ctx.req.headers;
+ return {
+ props: {
+ guild: code.guild,
+ guildName: code.guildName,
+ guildIcon: code.guildIcon,
+ user: code.user,
+ username: code.username,
+ data: code.data,
+ headers: headers
+ }
+ }
+}
\ No newline at end of file