From f2073f951d3959046e36ca5ef9c8805ec9c6fd8e Mon Sep 17 00:00:00 2001 From: Sean Edmunds Date: Fri, 24 Jan 2025 15:41:21 -0600 Subject: [PATCH] Toasts working --- src/App.tsx | 2 + src/components/ThemeProvider.tsx | 50 +++++++ src/components/ToastError.tsx | 16 --- src/hooks/useAPI.ts | 132 ++++-------------- src/hooks/useCommonHooks.ts | 4 + src/index.css | 4 + .../homepage/components/SettingsButton.tsx | 6 +- src/styles/Stack.module.css | 2 +- 8 files changed, 96 insertions(+), 120 deletions(-) delete mode 100644 src/components/ToastError.tsx diff --git a/src/App.tsx b/src/App.tsx index 8317db1..4aea686 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -21,6 +21,7 @@ import 'mantine-react-table/styles.css'; //import MRT styles import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import './index.css'; import { Homepage, Settings } from 'pages'; +import { ToastContainer } from 'react-toastify'; function App() { const { data: allThemes, isFetched: isAllThemesFetched } = useQueryAPI({ @@ -65,6 +66,7 @@ function App() { {theme && ( + diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx index 40a4070..febe83d 100644 --- a/src/components/ThemeProvider.tsx +++ b/src/components/ThemeProvider.tsx @@ -12,6 +12,56 @@ export function ThemeProvider({ '--color-background': theme.backgroundColor, '--color-border': theme.borderColor, '--color-search-background': theme.searchColor, + '--toastify-color-light': `hwb(from ${theme.primaryColor} h w b / 0.25)`, + '--toastify-color-dark': `hwb(from ${theme.primaryColor} h w b / 0.25)`, + '--toastify-color-info': '#3498db', + '--toastify-color-success': '#07bc0c', + '--toastify-color-warning': '#f1c40f', + '--toastify-color-error': 'hsl(6, 78%, 57%)', + '--toastify-color-transparent': 'rgba(255, 255, 255, 0.7)', + '--toastify-icon-color-info': 'var(--toastify-color-info)', + '--toastify-icon-color-success': 'var(--toastify-color-success)', + '--toastify-icon-color-warning': 'var(--toastify-color-warning)', + '--toastify-icon-color-error': 'var(--toastify-color-error)', + + '--toastify-container-width': 'fit-content', + '--toastify-toast-width': '320px', + '--toastify-toast-offset': '16px', + '--toastify-toast-top': + 'max(var(--toastify-toast-offset), env(safe-area-inset-top))', + '--toastify-toast-right': + 'max(var(--toastify-toast-offset), env(safe-area-inset-right))', + '--toastify-toast-left': + 'max(var(--toastify-toast-offset), env(safe-area-inset-left))', + '--toastify-toast-bottom': + 'max(var(--toastify-toast-offset), env(safe-area-inset-bottom))', + '--toastify-toast-background': '#fff', + '--toastify-toast-padding': '14px', + '--toastify-toast-min-height': '64px', + '--toastify-toast-max-height': '800px', + '--toastify-toast-bd-radius': '6px', + '--toastify-toast-shadow': '0px 4px 12px rgba(0, 0, 0, 0.1)', + '--toastify-font-family': 'sans-serif', + '--toastify-z-index': '9999', + '--toastify-text-color-light': theme.primaryColor, + '--toastify-text-color-dark': theme.primaryColor, + + /* Used only for colored theme */ + '--toastify-text-color-info': '#fff', + '--toastify-text-color-success': '#fff', + '--toastify-text-color-warning': '#fff', + '--toastify-text-color-error': '#fff', + + '--toastify-spinner-color': '#616161', + '--toastify-spinner-color-empty-area': '#e0e0e0', + '--toastify-color-progress-light': theme.accentColor, + '--toastify-color-progress-dark': '#bb86fc', + '--toastify-color-progress-info': 'var(--toastify-color-info)', + '--toastify-color-progress-success': 'var(--toastify-color-success)', + '--toastify-color-progress-warning': 'var(--toastify-color-warning)', + '--toastify-color-progress-error': 'var(--toastify-color-error)', + /* used to control the opacity of the progress trail */ + '--toastify-color-progress-bgo': 0.2, }} > {children} diff --git a/src/components/ToastError.tsx b/src/components/ToastError.tsx deleted file mode 100644 index 11c5ad6..0000000 --- a/src/components/ToastError.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Stack, Text } from '@mantine/core'; -import { stackClasses } from 'styles'; - -export function ToastError({ err }: { err: any }) { - const errorResponse = JSON.parse(err.message); - return ( - - - Status: {errorResponse.status} {errorResponse.statusText} - - Details: {errorResponse.msg} - {errorResponse.loc && Location: {errorResponse.loc}} - {errorResponse.type && Type: {errorResponse.type}} - - ); -} diff --git a/src/hooks/useAPI.ts b/src/hooks/useAPI.ts index 883c75d..a9c625e 100644 --- a/src/hooks/useAPI.ts +++ b/src/hooks/useAPI.ts @@ -1,6 +1,6 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useCommonHooks } from 'hooks'; import { useCallback } from 'react'; -import { toast } from 'react-toastify'; const url = `${import.meta.env.PROD ? import.meta.env.VITE_DOMAIN_PROD : import.meta.env.VITE_DOMAIN_DEV}/${import.meta.env.VITE_BASE_URL}`; @@ -32,32 +32,8 @@ export function useQueryAPI({ endpoint }: { endpoint: string }) { }); } -export function useWeatherAPI({ endpoint }: { endpoint: string }) { - let url = ''; - if (endpoint === 'baseline') { - url = 'https://api.weather.gov/gridpoints/HGX/55,96'; - } else if (endpoint === 'current') { - url = 'https://api.weather.gov/stations/KSGR/observations'; - } else if (endpoint === 'forecast') { - url = 'https://api.weather.gov/gridpoints/HGX/55,96/forecast'; - } else if (endpoint === 'hourly') { - url = 'https://api.weather.gov/gridpoints/HGX/55,96/forecast/hourly'; - } - const callEndpoint = async () => { - const response = await fetch(url); - if (!response.ok) { - throw new Error(`${response.status} ${response.statusText}`); - } - return await response.json(); - }; - - return useQuery({ - queryKey: ['GET', url], - queryFn: () => callEndpoint(), - }); -} - export function useMutationAPI() { + const { notify } = useCommonHooks(); const callEndpoint = async ( method: string, endpoint: string, @@ -76,9 +52,10 @@ export function useMutationAPI() { }, body: JSON.stringify(body), }; - + notify('Sending...'); const response = await fetch(`${url}/${endpoint}`, options); if (!response.ok) { + notify('Error!'); const responseData = await response.json(); if (typeof responseData.detail !== 'string') { const errorResponse = JSON.stringify({ @@ -114,6 +91,7 @@ export function useMutationAPI() { throw new Error(errorResponse); } + notify('Success!'); return await response.json(); }; @@ -137,6 +115,31 @@ export function useMutationAPI() { }); } +export function useWeatherAPI({ endpoint }: { endpoint: string }) { + let url = ''; + if (endpoint === 'baseline') { + url = 'https://api.weather.gov/gridpoints/HGX/55,96'; + } else if (endpoint === 'current') { + url = 'https://api.weather.gov/stations/KSGR/observations'; + } else if (endpoint === 'forecast') { + url = 'https://api.weather.gov/gridpoints/HGX/55,96/forecast'; + } else if (endpoint === 'hourly') { + url = 'https://api.weather.gov/gridpoints/HGX/55,96/forecast/hourly'; + } + const callEndpoint = async () => { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`${response.status} ${response.statusText}`); + } + return await response.json(); + }; + + return useQuery({ + queryKey: ['GET', url], + queryFn: () => callEndpoint(), + }); +} + export function useFileUploadAPI() { const callEndpoint = async ( method: string, @@ -319,78 +322,3 @@ export function useFetchAllRecordsAPI({ endpoint }: { endpoint: string }) { invalidate, }; } - -interface DownloadFileOptions { - endpoint: string; - file_name: string; -} - -export function useDownloadFile() { - const downloadFile = useCallback(async ({ file_name }: DownloadFileOptions) => { - const options: any = { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': '*', - 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', - 'Access-Control-Allow-Credentials': true, - 'Sec-Fetch-Mode': 'no-cors', - 'Sec-Fetch-Site': 'same-site', - }, - }; - const toastID = toast.loading('Processing...'); - try { - const response = await fetch(url, options); - if (!response.ok) { - throw new Error('Network response was not ok'); - } - - const blob = await response.blob(); - if (blob.type === 'application/json') { - const blob_text = await blob.text(); - const cleaned_text = blob_text.replace(/"/g, ''); - toast.update(toastID, { - render: cleaned_text, - type: 'info', - isLoading: false, - autoClose: 5000, - closeButton: null, - }); - return; - } - - if (typeof window !== 'undefined') { - const blobURL = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - - a.style.display = 'none'; - a.href = blobURL; - a.download = file_name; - - document.body.appendChild(a); - a.click(); - window.URL.revokeObjectURL(blobURL); - document.body.removeChild(a); - toast.update(toastID, { - render: `${file_name} Downloaded`, - type: 'success', - isLoading: false, - autoClose: 5000, - closeButton: null, - }); - } - } catch (error) { - console.error('Download failed:', error); - toast.update(toastID, { - render: `Error Downloading ${file_name}. Please try again.`, - type: 'error', - isLoading: false, - autoClose: 5000, - closeButton: null, - }); - } - }, []); - - return downloadFile; -} diff --git a/src/hooks/useCommonHooks.ts b/src/hooks/useCommonHooks.ts index 3ef31ab..66ad763 100644 --- a/src/hooks/useCommonHooks.ts +++ b/src/hooks/useCommonHooks.ts @@ -2,6 +2,7 @@ import { useLocalStorage } from '@mantine/hooks'; import { appTheme } from 'contexts'; import { useAtom } from 'jotai'; import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; import { useQueryAPI, useWeatherAPI } from './useAPI'; export function useCommonHooks() { @@ -95,6 +96,8 @@ export function useCommonHooks() { const [applicationData, setApplicationData] = useState([]); + const notify = (notification: any) => toast(notification, { position: 'bottom-right' }); + useEffect(() => { if (apps && !isAppsFetching) { setApplicationData(apps); @@ -200,5 +203,6 @@ export function useCommonHooks() { personalIsFetched, personalIsFetching, personalIsLoading, + notify, }; } diff --git a/src/index.css b/src/index.css index 5cac195..20c8b1b 100644 --- a/src/index.css +++ b/src/index.css @@ -9,4 +9,8 @@ color: var(--color-text-pri) !important; background-color: var(--color-text-pri) !important; } +} + +.Toastify__toast-theme--light { + backdrop-filter: blur(10px) !important; } \ No newline at end of file diff --git a/src/pages/homepage/components/SettingsButton.tsx b/src/pages/homepage/components/SettingsButton.tsx index b260c1d..6a5bf05 100644 --- a/src/pages/homepage/components/SettingsButton.tsx +++ b/src/pages/homepage/components/SettingsButton.tsx @@ -36,6 +36,7 @@ function SettingsButton() { bookmarkFilter, setBookmarkFilter, isMobile, + notify, } = useCommonHooks(); useEffect(() => { @@ -87,7 +88,10 @@ function SettingsButton() {