diff --git a/README.md b/README.md
new file mode 100644
index 0000000..195ca58
--- /dev/null
+++ b/README.md
@@ -0,0 +1,17 @@
+# reminder-dashboard
+
+The re-re-rewrite of the dashboard.
+
+## Why
+
+The existing beta variant of the dashboard is written using vanilla JavaScript. This is fine,
+but annoying to update. This would've been okay if I was more dedicated to updating the vanilla
+JavaScript too, but I want to experiment with "new" things.
+
+This also allows me to expand my frontend skills, which is relevant to part of my job.
+
+## Developing
+
+1. Download the parent repo: https://gitea.jellypro.xyz/jude/reminder-bot
+2. Initialise the submodules
+3. Run both `npm start` and `cargo run`
\ No newline at end of file
diff --git a/src/api.ts b/src/api.ts
index 1b1c12d..7666998 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -129,7 +129,7 @@ export const fetchGuildReminders = (guild: string) => ({
staleTime: OTHER_STALE_TIME,
});
-export const mutateGuildReminder = (guild: string) => ({
+export const patchGuildReminder = (guild: string) => ({
mutationFn: (reminder: Reminder) =>
axios.patch(`/dashboard/api/guild/${guild}/reminders`, {
...reminder,
@@ -137,6 +137,15 @@ export const mutateGuildReminder = (guild: string) => ({
}),
});
+export const deleteGuildReminder = (guild: string) => ({
+ mutationFn: (reminder: Reminder) =>
+ axios.delete(`/dashboard/api/guild/${guild}/reminders`, {
+ data: {
+ uid: reminder.uid,
+ },
+ }),
+});
+
export const fetchGuildTemplates = (guild: string) => ({
queryKey: ["GUILD_TEMPLATES", guild],
queryFn: () =>
diff --git a/src/components/Reminder/ButtonRow/DeleteButton.tsx b/src/components/Reminder/ButtonRow/DeleteButton.tsx
new file mode 100644
index 0000000..4db109c
--- /dev/null
+++ b/src/components/Reminder/ButtonRow/DeleteButton.tsx
@@ -0,0 +1,68 @@
+import { useState } from "preact/hooks";
+import { Modal } from "../../Modal";
+import { useMutation, useQueryClient } from "react-query";
+import { useReminder } from "../ReminderContext";
+import { deleteGuildReminder } from "../../../api";
+import { useParams } from "wouter";
+
+export const DeleteButton = () => {
+ const [modalOpen, setModalOpen] = useState(false);
+
+ return (
+ <>
+
+ {modalOpen && }
+ >
+ );
+};
+
+const DeleteModal = ({ setModalOpen }) => {
+ const [reminder] = useReminder();
+ const { guild } = useParams();
+
+ const queryClient = useQueryClient();
+ const mutation = useMutation({
+ ...deleteGuildReminder(guild),
+ onSuccess: () => {
+ queryClient.invalidateQueries({
+ queryKey: ["GUILD_REMINDERS", guild],
+ });
+ setModalOpen(false);
+ },
+ });
+
+ return (
+
+ <>
+ This reminder will be permanently deleted. Are you sure?
+
+
+
+
+
+ >
+
+ );
+};
diff --git a/src/components/Reminder/ButtonRow/EditButtonRow.tsx b/src/components/Reminder/ButtonRow/EditButtonRow.tsx
new file mode 100644
index 0000000..8522964
--- /dev/null
+++ b/src/components/Reminder/ButtonRow/EditButtonRow.tsx
@@ -0,0 +1,68 @@
+import { useState } from "preact/hooks";
+import { useMutation, useQueryClient } from "react-query";
+import { patchGuildReminder } from "../../../api";
+import { useParams } from "wouter";
+import { ICON_FLASH_TIME } from "../../../consts";
+import { DeleteButton } from "./DeleteButton";
+import { useReminder } from "../ReminderContext";
+
+export const EditButtonRow = () => {
+ const { guild } = useParams();
+ const [reminder, setReminder] = useReminder();
+
+ const [recentlySaved, setRecentlySaved] = useState(false);
+ const queryClient = useQueryClient();
+
+ const mutation = useMutation({
+ ...patchGuildReminder(guild),
+ onSuccess: () => {
+ queryClient.invalidateQueries({
+ queryKey: ["GUILD_REMINDERS", guild],
+ });
+ setRecentlySaved(true);
+ setTimeout(() => {
+ setRecentlySaved(false);
+ }, ICON_FLASH_TIME);
+ },
+ });
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/src/components/Reminder/EditReminder.tsx b/src/components/Reminder/EditReminder.tsx
index 5d1e9f7..6324504 100644
--- a/src/components/Reminder/EditReminder.tsx
+++ b/src/components/Reminder/EditReminder.tsx
@@ -1,15 +1,12 @@
-import { fetchGuildChannels, fetchUserInfo, mutateGuildReminder, Reminder } from "../../api";
-import { useMutation, useQueries, useQueryClient } from "react-query";
+import { fetchGuildChannels, Reminder } from "../../api";
+import { useQuery } from "react-query";
import { useParams } from "wouter";
import { Name } from "./Name";
-import { Username } from "./Username";
-import { Content } from "./Content";
-import { ChannelSelector } from "./ChannelSelector";
import { useState } from "preact/hooks";
-import { IntervalSelector } from "./IntervalSelector";
-import { Embed } from "./Embed";
-import { DateTime } from "luxon";
-import { ICON_FLASH_TIME } from "../../consts";
+import { EditButtonRow } from "./ButtonRow/EditButtonRow";
+import { Message } from "./Message";
+import { Settings } from "./Settings";
+import { ReminderContext } from "./ReminderContext";
type Props = {
reminder: Reminder;
@@ -19,229 +16,40 @@ export const EditReminder = ({ reminder: initialReminder }: Props) => {
const { guild } = useParams();
const [reminder, setReminder] = useState(initialReminder);
- const queryClient = useQueryClient();
- const mutation = useMutation({
- ...mutateGuildReminder(guild),
- onSuccess: () => {
- queryClient.invalidateQueries({
- queryKey: ["GUILD_REMINDERS", guild],
- });
- setRecentlySaved(true);
- setTimeout(() => {
- setRecentlySaved(false);
- }, ICON_FLASH_TIME);
- },
- });
-
- const [
- { isSuccess: channelsFetched, data: guildChannels },
- { isSuccess: userFetched, data: userInfo },
- ] = useQueries([fetchGuildChannels(guild), fetchUserInfo()]);
+ const { isSuccess: channelsFetched, data: guildChannels } = useQuery(fetchGuildChannels(guild));
const [collapsed, setCollapsed] = useState(false);
- const [recentlySaved, setRecentlySaved] = useState(false);
- if (!channelsFetched || !userFetched) {
- // todo
+ if (!channelsFetched) {
return <>>;
}
const channelInfo = guildChannels.find((c) => c.id === reminder.channel);
return (
-
-
-
#{channelInfo.name}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- setReminder((reminder) => ({
- ...reminder,
- username,
- }));
- }}
- >
- {
- setReminder((reminder) => ({
- ...reminder,
- content,
- }));
- }}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
#{channelInfo.name}
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
);
};
diff --git a/src/components/Reminder/Message.tsx b/src/components/Reminder/Message.tsx
new file mode 100644
index 0000000..54b222e
--- /dev/null
+++ b/src/components/Reminder/Message.tsx
@@ -0,0 +1,54 @@
+import { ImagePicker } from "./ImagePicker";
+import { Username } from "./Username";
+import { Content } from "./Content";
+import { Embed } from "./Embed";
+import { useReminder } from "./ReminderContext";
+
+export const Message = () => {
+ const [reminder, setReminder] = useReminder();
+
+ return (
+
+
+
+
+ {
+ setReminder((reminder) => ({
+ ...reminder,
+ avatar: url,
+ }));
+ }}
+ >
+
+
+
+
+ {
+ setReminder((reminder) => ({
+ ...reminder,
+ username,
+ }));
+ }}
+ >
+ {
+ setReminder((reminder) => ({
+ ...reminder,
+ content,
+ }));
+ }}
+ >
+
+
+
+
+
+ );
+};
diff --git a/src/components/Reminder/ReminderContext.tsx b/src/components/Reminder/ReminderContext.tsx
new file mode 100644
index 0000000..e4257eb
--- /dev/null
+++ b/src/components/Reminder/ReminderContext.tsx
@@ -0,0 +1,9 @@
+import { createContext } from "preact";
+import { useContext } from "preact/compat";
+import { Reminder } from "../../api";
+
+export const ReminderContext = createContext<
+ [Reminder, (r: (reminder: Reminder) => Reminder) => void]
+>([null, () => {}]);
+
+export const useReminder = () => useContext(ReminderContext);
diff --git a/src/components/Reminder/Settings.tsx b/src/components/Reminder/Settings.tsx
new file mode 100644
index 0000000..fa62685
--- /dev/null
+++ b/src/components/Reminder/Settings.tsx
@@ -0,0 +1,116 @@
+import { ChannelSelector } from "./ChannelSelector";
+import { DateTime } from "luxon";
+import { IntervalSelector } from "./IntervalSelector";
+import { useQuery } from "react-query";
+import { fetchUserInfo } from "../../api";
+import { useReminder } from "./ReminderContext";
+
+export const Settings = () => {
+ const { isSuccess: userFetched, data: userInfo } = useQuery(fetchUserInfo());
+
+ const [reminder, setReminder] = useReminder();
+
+ if (!userFetched) {
+ return <>>;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};