diff --git a/src/api.ts b/src/api.ts index bd6b990..bb24cf8 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,6 +1,5 @@ import axios from "axios"; import { DateTime } from "luxon"; -import { QueryClient } from "react-query"; type UserInfo = { name: string; @@ -89,6 +88,10 @@ export const fetchUserInfo = () => ({ staleTime: USER_INFO_STALE_TIME, }); +export const patchUserInfo = () => ({ + mutationFn: (user: UserInfo) => axios.patch(`/dashboard/api/user`, user), +}); + export const fetchUserGuilds = () => ({ queryKey: ["USER_GUILDS"], queryFn: () => diff --git a/src/components/App/FlashContext.tsx b/src/components/App/FlashContext.tsx index a7d9cb5..17729f7 100644 --- a/src/components/App/FlashContext.tsx +++ b/src/components/App/FlashContext.tsx @@ -1,6 +1,7 @@ import { createContext } from "preact"; import { useContext } from "preact/compat"; +import { Message } from "./FlashProvider"; -export const FlashContext = createContext(null); +export const FlashContext = createContext(null as (message: Message) => void); export const useFlash = () => useContext(FlashContext); diff --git a/src/components/App/FlashProvider.tsx b/src/components/App/FlashProvider.tsx index e2e12d2..dc9b576 100644 --- a/src/components/App/FlashProvider.tsx +++ b/src/components/App/FlashProvider.tsx @@ -2,13 +2,18 @@ import { FlashContext } from "./FlashContext"; import { useState } from "preact/hooks"; import { MESSAGE_FLASH_TIME } from "../../consts"; +export type Message = { + message: string; + type: "error" | "success"; +}; + export const FlashProvider = ({ children }) => { - const [messages, setMessages] = useState([] as string[]); + const [messages, setMessages] = useState([] as Message[]); return ( { - setMessages((messages: string[]) => [...messages, message]); + value={(message: Message) => { + setMessages((messages: Message[]) => [...messages, message]); setTimeout(() => { setMessages((messages) => [...messages].splice(1)); }, MESSAGE_FLASH_TIME); @@ -16,14 +21,22 @@ export const FlashProvider = ({ children }) => { > <> {children} - {messages.map((message) => ( - - - - {" "} - {message} - - ))} + + {messages.map((message) => { + const className = message.type === "error" ? "is-danger" : "is-success"; + const icon = + message.type === "error" ? "fa-exclamation-circle" : "fa-check"; + + return ( + + + + {" "} + {message.message} + + ); + })} + > ); diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 1b8347e..dbdbb2f 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -13,7 +13,7 @@ export function App() { - + diff --git a/src/components/Reminder/ButtonRow/CreateButtonRow.tsx b/src/components/Reminder/ButtonRow/CreateButtonRow.tsx index 28e21e7..ef579d2 100644 --- a/src/components/Reminder/ButtonRow/CreateButtonRow.tsx +++ b/src/components/Reminder/ButtonRow/CreateButtonRow.tsx @@ -19,8 +19,15 @@ export const CreateButtonRow = () => { ...postGuildReminder(guild), onSuccess: (data) => { if (data.error) { - flash(data.error); + flash({ + message: data.error, + type: "error", + }); } else { + flash({ + message: "Reminder created", + type: "success", + }); queryClient.invalidateQueries({ queryKey: ["GUILD_REMINDERS", guild], }); diff --git a/src/components/Reminder/ButtonRow/DeleteButton.tsx b/src/components/Reminder/ButtonRow/DeleteButton.tsx index 4db109c..1dbf33f 100644 --- a/src/components/Reminder/ButtonRow/DeleteButton.tsx +++ b/src/components/Reminder/ButtonRow/DeleteButton.tsx @@ -4,6 +4,7 @@ import { useMutation, useQueryClient } from "react-query"; import { useReminder } from "../ReminderContext"; import { deleteGuildReminder } from "../../../api"; import { useParams } from "wouter"; +import { useFlash } from "../../App/FlashContext"; export const DeleteButton = () => { const [modalOpen, setModalOpen] = useState(false); @@ -27,10 +28,15 @@ const DeleteModal = ({ setModalOpen }) => { const [reminder] = useReminder(); const { guild } = useParams(); + const flash = useFlash(); const queryClient = useQueryClient(); const mutation = useMutation({ ...deleteGuildReminder(guild), onSuccess: () => { + flash({ + message: "Reminder deleted", + type: "success", + }); queryClient.invalidateQueries({ queryKey: ["GUILD_REMINDERS", guild], }); diff --git a/src/components/Reminder/ButtonRow/EditButtonRow.tsx b/src/components/Reminder/ButtonRow/EditButtonRow.tsx index 4128b80..a3c8f21 100644 --- a/src/components/Reminder/ButtonRow/EditButtonRow.tsx +++ b/src/components/Reminder/ButtonRow/EditButtonRow.tsx @@ -14,8 +14,6 @@ export const EditButtonRow = () => { const [recentlySaved, setRecentlySaved] = useState(false); const queryClient = useQueryClient(); - const flash = useFlash(); - const mutation = useMutation({ ...patchGuildReminder(guild), onSuccess: () => { @@ -27,9 +25,6 @@ export const EditButtonRow = () => { setRecentlySaved(false); }, ICON_FLASH_TIME); }, - onError: (error) => { - flash(error); - }, }); return ( diff --git a/src/components/Reminder/LoadTemplate.tsx b/src/components/Reminder/LoadTemplate.tsx index b1787aa..ed03d81 100644 --- a/src/components/Reminder/LoadTemplate.tsx +++ b/src/components/Reminder/LoadTemplate.tsx @@ -25,14 +25,25 @@ export const LoadTemplate = () => { const LoadTemplateModal = ({ setModalOpen }) => { const { guild } = useParams(); - const { status, data: templates } = useQuery(fetchGuildTemplates(guild)); + const [reminder, setReminder] = useReminder(); + const { isSuccess, data: templates } = useQuery(fetchGuildTemplates(guild)); + + const [selected, setSelected] = useState(null); return ( - - {templates !== undefined && + { + setSelected(ev.currentTarget.value); + }} + > + + Choose template... + + {isSuccess && templates.map((template) => ( {template.name} ))} @@ -44,7 +55,17 @@ const LoadTemplateModal = ({ setModalOpen }) => { - + { + setReminder((reminder) => ({ + ...reminder, + // todo this probably needs to exclude some things + ...templates.find((template) => template.id === selected), + })); + }} + > Load Template diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index baf3123..1ec2b03 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -5,6 +5,8 @@ import { Brand } from "./Brand"; import { Wave } from "./Wave"; import { GuildEntry } from "./GuildEntry"; import { fetchUserGuilds, GuildInfo } from "../../api"; +import { useState } from "preact/hooks"; +import { TimezonePicker } from "../TimezonePicker"; type ContentProps = { guilds: GuildInfo[]; @@ -32,12 +34,7 @@ const SidebarContent = ({ guilds }: ContentProps) => { {" "} Import/Export - - - - {" "} - Timezone - + diff --git a/src/components/TimezonePicker/index.tsx b/src/components/TimezonePicker/index.tsx index afe4ee0..df0398e 100644 --- a/src/components/TimezonePicker/index.tsx +++ b/src/components/TimezonePicker/index.tsx @@ -1,7 +1,8 @@ import { DateTime } from "luxon"; import { useQuery } from "react-query"; -import { QueryKeys } from "../../consts"; import { fetchUserInfo } from "../../api"; +import { Modal } from "../Modal"; +import { useState } from "preact/hooks"; type DisplayProps = { timezone: string; @@ -27,73 +28,72 @@ const TimezoneDisplay = ({ timezone }: DisplayProps) => { ); }; -const TimezonePicker = () => { - const browserTimezone = DateTime.now().zone.name; - - const { isLoading, isError, data } = useQuery({ - queryKey: QueryKeys.USER_DATA, - queryFn: fetchUserInfo, - }); +export const TimezonePicker = () => { + const [modalOpen, setModalOpen] = useState(false); return ( - - - - - - Update Timezone{" "} - - - - - - - - - - - Your configured timezone is:{" "} - - - - Your browser timezone is:{" "} - - - {!isError && ( - <> - Your bot timezone is:{" "} - {isLoading ? ( - - ) : ( - - )} - > - )} - - - - - - Use Browser Timezone{" "} - - - - - - Use Bot Timezone{" "} - - - - - - Set Bot Timezone - - - - - - + <> + { + setModalOpen(true); + }} + > + + + {" "} + Timezone + + {modalOpen && } + > + ); +}; + +const TimezoneModal = ({ setModalOpen }) => { + const browserTimezone = DateTime.now().zone.name; + + const { isLoading, isError, data } = useQuery(fetchUserInfo()); + + return ( + + + Your configured timezone is:{" "} + + + + Your browser timezone is:{" "} + + + {!isError && ( + <> + Your bot timezone is:{" "} + {isLoading ? ( + + ) : ( + + )} + > + )} + + + + + Use Browser Timezone{" "} + + + + + + Use Bot Timezone{" "} + + + + + + Set Bot Timezone + + + ); };
- Your configured timezone is:{" "} - - - - Your browser timezone is:{" "} - - - {!isError && ( - <> - Your bot timezone is:{" "} - {isLoading ? ( - - ) : ( - - )} - > - )} -
+ Your configured timezone is:{" "} + + + + Your browser timezone is:{" "} + + + {!isError && ( + <> + Your bot timezone is:{" "} + {isLoading ? ( + + ) : ( + + )} + > + )} +