diff --git a/src/components/Popup.tsx b/src/components/Popup.tsx
new file mode 100644
index 00000000..396c30e0
--- /dev/null
+++ b/src/components/Popup.tsx
@@ -0,0 +1,76 @@
+import { useEffect } from "react";
+import { HiOutlineExclamationCircle } from "react-icons/hi2";
+import { HiXMark } from "react-icons/hi2";
+import { Transition } from "@headlessui/react";
+
+import { usePopup } from "~/providers/popup";
+
+const Popup: React.FC = () => {
+ const { isOpen, popupHeader, popupMessage, hidePopup } = usePopup();
+
+ useEffect(() => {
+ if (isOpen) {
+ const timer = setTimeout(() => {
+ hidePopup();
+ }, 5000);
+
+ return () => clearTimeout(timer);
+ }
+ }, [isOpen, hidePopup]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ {popupHeader}
+
+
+ {popupMessage}
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default Popup;
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 1bf598aa..087df155 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -5,6 +5,7 @@ import { Plus_Jakarta_Sans } from "next/font/google";
import { ModalProvider } from "~/providers/modal";
import { BoardProvider } from "~/providers/board";
+import { PopupProvider } from "~/providers/popup";
import { ThemeProvider } from "~/providers/theme";
import { api } from "~/utils/api";
@@ -33,9 +34,11 @@ const MyApp: AppType = ({ Component, pageProps }) => {
-
-
-
+
+
+
+
+
diff --git a/src/pages/boards/[...boardId]/index.tsx b/src/pages/boards/[...boardId]/index.tsx
index a249463f..8bb46d5e 100644
--- a/src/pages/boards/[...boardId]/index.tsx
+++ b/src/pages/boards/[...boardId]/index.tsx
@@ -1,5 +1,6 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/dashboard";
+import Popup from "~/components/Popup";
import BoardView from "~/views/board";
export default function BoardPage() {
@@ -8,6 +9,7 @@ export default function BoardPage() {
+
);
}
diff --git a/src/pages/boards/index.tsx b/src/pages/boards/index.tsx
index 2c8beb9a..61333c93 100644
--- a/src/pages/boards/index.tsx
+++ b/src/pages/boards/index.tsx
@@ -1,5 +1,6 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/dashboard";
+import Popup from "~/components/Popup";
import BoardsView from "~/views/boards";
export default function BoardsPage() {
@@ -8,6 +9,7 @@ export default function BoardsPage() {
+
);
}
diff --git a/src/providers/board.tsx b/src/providers/board.tsx
index 107ce580..6143f514 100644
--- a/src/providers/board.tsx
+++ b/src/providers/board.tsx
@@ -6,6 +6,7 @@ import React, {
} from "react";
import { api } from "~/utils/api";
+import { usePopup } from "~/providers/popup";
import {
type GetBoardByIdOutput,
@@ -40,6 +41,8 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({
const [boardData, setBoardData] =
useState(initialBoardData);
+ const { showPopup } = usePopup();
+
const refetchBoard = async () => {
if (boardData?.publicId) {
try {
@@ -52,10 +55,24 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({
const updateCardMutation = api.card.reorder.useMutation({
onSuccess: () => refetchBoard(),
+ onError: () => {
+ refetchBoard();
+ showPopup({
+ header: "Unable to update card",
+ message: "Please try again later, or contact customer support.",
+ });
+ },
});
const updateListMutation = api.list.reorder.useMutation({
onSuccess: () => refetchBoard(),
+ onError: () => {
+ refetchBoard();
+ showPopup({
+ header: "Unable to update list",
+ message: "Please try again later, or contact customer support.",
+ });
+ },
});
const updateList = ({
diff --git a/src/providers/popup.tsx b/src/providers/popup.tsx
new file mode 100644
index 00000000..a61a0255
--- /dev/null
+++ b/src/providers/popup.tsx
@@ -0,0 +1,53 @@
+import { createContext, useContext, useState } from "react";
+
+type PopupContextType = {
+ isOpen: boolean;
+ showPopup: (params: { header: string; message: string }) => void;
+ hidePopup: () => void;
+ popupHeader: string;
+ popupMessage: string;
+};
+
+interface Props {
+ children: React.ReactNode;
+}
+
+const PopupContext = createContext(undefined);
+
+export const PopupProvider: React.FC = ({ children }) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const [popupHeader, setPopupHeader] = useState("");
+ const [popupMessage, setPopupMessage] = useState("");
+
+ const showPopup = ({
+ header,
+ message,
+ }: {
+ header: string;
+ message: string;
+ }) => {
+ setIsOpen(true);
+ setPopupHeader(header);
+ setPopupMessage(message);
+ };
+
+ const hidePopup = () => {
+ setIsOpen(false);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const usePopup = () => {
+ const context = useContext(PopupContext);
+ if (context === undefined) {
+ throw new Error("usePopup must be used within a PopupProvider");
+ }
+ return context;
+};