Skip to content

Commit

Permalink
Refactor notification and use sessionstorage
Browse files Browse the repository at this point in the history
  • Loading branch information
WCY-dt committed May 7, 2024
1 parent 67b82ff commit 292ebdb
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 112 deletions.
8 changes: 5 additions & 3 deletions src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useRef, useContext } from 'react';
import { Icon } from '@iconify/react';
import { Link } from 'react-router-dom';

import { useNotification } from '../hooks/notificationContext';
import { AppContext } from '../contexts/context';
import Login from '../popups/login';

Expand All @@ -14,10 +15,11 @@ function Header() {
showMobileMenu, setShowMobileMenu,
routes,
setToken,
dispatchNotification,
searchTerm, setSearchTerm
} = useContext(AppContext);

const setNotification = useNotification();

const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (inputRef.current) {
Expand All @@ -44,8 +46,8 @@ function Header() {
const onClickLogout = () => {
setLogin(false);
setToken('');
localStorage.removeItem('token');
dispatchNotification({ type: 'SUCCESS', message: 'Logout' });
sessionStorage.removeItem('token');
setNotification({ type: 'SUCCESS', message: 'logout' });
};

return (
Expand Down
8 changes: 5 additions & 3 deletions src/components/linkCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useContext } from 'react';
import { Icon } from '@iconify/react';
import { v4 as uuidv4 } from 'uuid';

import { useNotification } from '../hooks/notificationContext';
import { AppContext } from '../contexts/context';
import { getRandomColor, getContrastColor } from '../utils/randomColor';
import deleteCardHandler from '../services/deleteCardHandler';
Expand All @@ -16,7 +17,6 @@ function LinkCard({ item }: LinkCardProps) {
const {
isLogin,
token,
dispatchNotification,
setShowConfirm,
setConfirmMessage,
setConfirmAction,
Expand All @@ -26,6 +26,8 @@ function LinkCard({ item }: LinkCardProps) {
setEditType
} = useContext(AppContext);

const setNotification = useNotification();

const id = item.Id || 0;

const backgroundColor = getRandomColor(item.Category);
Expand All @@ -46,9 +48,9 @@ function LinkCard({ item }: LinkCardProps) {
const deleteCardResult = await deleteCardHandler({ id, token });

if (deleteCardResult === true) {
dispatchNotification({ type: 'SUCCESS', message: 'Card delete' });
setNotification({ type: 'SUCCESS', message: 'Card delete' });
} else {
dispatchNotification({ type: 'ERROR', message: 'Card delete' });
setNotification({ type: 'ERROR', message: 'Card delete' });
}
};

Expand Down
33 changes: 5 additions & 28 deletions src/contexts/context.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
import React, { createContext, useState, useEffect, useReducer } from 'react';
import React, { createContext, useState, useEffect } from 'react';
import { fetchCollection } from '../services/collectionFetcher';

export type NotificationState = {
type: string;
message: string;
};
export type NotificationAction = {
type: 'SUCCESS' | 'ERROR';
message: string;
};
const notificationReducer = (state: NotificationState, action: NotificationAction) => {
switch (action.type) {
case 'SUCCESS':
return { ...state, type: 'SUCCESS', message: action.message };
case 'ERROR':
return { ...state, type: 'ERROR', message: action.message };
default:
return state;
}
}

export const AppContext = createContext({
isLoading: false,
setLoading: (_: boolean) => {},
Expand All @@ -35,9 +16,7 @@ export const AppContext = createContext({
setRoutes: (_: {[_: string]: React.ReactNode}) => {},
token: '',
setToken: (_: string) => {},
notification: { type: '', message: '' },
dispatchNotification: (_: NotificationAction) => {},
showConfirm: false,
showConfirm: false,
setShowConfirm: (_: boolean) => {},
confirmMessage: '',
setConfirmMessage: (_: string) => {},
Expand All @@ -63,7 +42,6 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
const [needReload, setNeedReload] = useState<boolean>(false);
const [routes, setRoutes] = useState({});
const [token, setToken] = useState<string>('');
const [notification, dispatchNotification] = useReducer(notificationReducer, { type: '', message: '' });
const [showConfirm, setShowConfirm] = useState<boolean>(false);
const [confirmMessage, setConfirmMessage] = useState<string>('');
const [confirmAction, setConfirmAction] = useState<() => void>(() => () => {});
Expand All @@ -80,14 +58,14 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
}, []);

useEffect(() => {
if (localStorage.getItem('token')) {
if (sessionStorage.getItem('token')) {
setLogin(true);
setToken(localStorage.getItem('token') as string);
setToken(sessionStorage.getItem('token') as string);
}
}, []);

useEffect(() => {
localStorage.removeItem('colorMap');
sessionStorage.removeItem('colorMap');
}, []);

return (
Expand All @@ -99,7 +77,6 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
needReload, setReload: setNeedReload,
routes, setRoutes,
token, setToken,
notification, dispatchNotification,
showConfirm, setShowConfirm,
confirmMessage, setConfirmMessage,
confirmAction, setConfirmAction,
Expand Down
75 changes: 75 additions & 0 deletions src/hooks/notificationContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React, { createContext, useState, useReducer, useEffect, useContext } from 'react';

import '../styles/popups/notification.css';

type NotificationAction = {
type: 'SUCCESS' | 'ERROR';
message: string;
};

interface NotificationContextType {
notification: NotificationAction;
updateNotification: (action: NotificationAction) => void;
}

const NotificationContext = createContext<NotificationContextType | null>(null);

const SUCCESS_MESSAGE_SUFFIX = ' successfully';
const ERROR_MESSAGE_SUFFIX = ' failed, please try again';

const notificationReducer = (state: NotificationAction, action: NotificationAction) => {
switch (action.type) {
case 'SUCCESS':
return { ...action, message: action.message + SUCCESS_MESSAGE_SUFFIX }
case 'ERROR':
return { ...action, message: action.message + ERROR_MESSAGE_SUFFIX }
default:
return state;
}
};

const VISIBILITY_DELAY = 2000;

export const NotificationProvider = ({ children }: { children: React.ReactNode }) => {
const [notification, dispatch] = useReducer(notificationReducer, { type: 'SUCCESS', message: '' });
const [showNotification, setShowNotification] = useState(false);

const updateNotification = (action: NotificationAction) => {
dispatch(action);
};

useEffect(() => {
let visibilityTimer: NodeJS.Timeout | null = null;

if (notification.message) {
setShowNotification(true);

visibilityTimer = setTimeout(() => {
setShowNotification(false);
}, VISIBILITY_DELAY);
}

return () => {
if (visibilityTimer) {
clearTimeout(visibilityTimer);
}
};
}, [notification]);

return (
<NotificationContext.Provider value={{ notification, updateNotification }}>
{children}
<div className={`notification ${showNotification ? 'show' : ''}`}>
{notification.message}
</div>
</NotificationContext.Provider>
);
};

export const useNotification = () => {
const context = useContext(NotificationContext);
if (!context) {
throw new Error('useNotification must be used within a NotificationProvider');
}
return context.updateNotification;
};
12 changes: 7 additions & 5 deletions src/popups/login.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useContext } from 'react';
import { Icon } from '@iconify/react';

import { useNotification } from '../hooks/notificationContext';
import { AppContext } from '../contexts/context';
import loginHandler from '../services/loginHandler';

Expand All @@ -11,22 +12,23 @@ function Login() {
const {
setShowLogin,
setLogin,
token, setToken,
dispatchNotification
token, setToken
} = useContext(AppContext);

const setNotification = useNotification();

const onClickLogin = async () => {
const username = (document.getElementById("username") as HTMLInputElement).value;
const password = (document.getElementById("password") as HTMLInputElement).value;
const loginResult = await loginHandler({ username, password, setToken });

if (loginResult === true) {
setShowLogin(false);
localStorage.setItem('token', token);
sessionStorage.setItem('token', token);
setLogin(true);
dispatchNotification({ type: 'SUCCESS', message: 'Login' });
setNotification({ type: 'SUCCESS', message: 'login' });
} else {
dispatchNotification({ type: 'ERROR', message: 'Login' });
setNotification({ type: 'ERROR', message: 'login' });
}
};

Expand Down
63 changes: 0 additions & 63 deletions src/popups/notification.tsx

This file was deleted.

8 changes: 5 additions & 3 deletions src/routers/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React, { useContext } from 'react';
import { BrowserRouter } from 'react-router-dom';

import { AppContext, AppProvider } from '../contexts/context';
import { NotificationProvider } from '../hooks/notificationContext';
import Header from '../components/header';
import Content from '../components/content';
import Footer from '../components/footer';
import Notification from '../popups/notification';
// import Notification from '../popups/notification';
import Confirm from '../popups/confirm';
import Edit from '../popups/edit';
import Overlay from '../popups/overlay';
Expand All @@ -15,7 +16,7 @@ import '../styles/popups/loading.css';


function Router() {
const { isLoading: isLoading } = useContext(AppContext);
const { isLoading } = useContext(AppContext);

if (isLoading) {
return (
Expand All @@ -25,16 +26,17 @@ function Router() {

return (
<AppProvider>
<NotificationProvider>
<BrowserRouter>
<Header />
<Content />
<Footer />
</BrowserRouter>
<Notification />
<ClearFilter />
<Confirm />
<Edit />
<Overlay />
</NotificationProvider>
</AppProvider>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/styles/popups/notification.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@

.notification.show {
opacity: 1;
}
}
6 changes: 3 additions & 3 deletions src/utils/randomColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ function generateRandomColor() {
}

export function getRandomColor(category: string) {
let colorMap = JSON.parse(localStorage.getItem('colorMap') ?? '{}') || { 'default': '#d1ecf1' };
let colorMap = JSON.parse(sessionStorage.getItem('colorMap') ?? '{}') || { 'default': '#d1ecf1' };

if (!colorMap[category]) {
let randomColor;
do {
randomColor = generateRandomColor();
} while (calculateBrightness(hexToRgb(randomColor)) > 200);
colorMap[category] = randomColor;
localStorage.setItem('colorMap', JSON.stringify(colorMap));
sessionStorage.setItem('colorMap', JSON.stringify(colorMap));
}

return colorMap[category] || colorMap['default'];
Expand All @@ -37,4 +37,4 @@ export function getContrastColor(color: string) {
const rgb = hexToRgb(color);
const brightness = calculateBrightness(rgb);
return (brightness >= 100) ? 'black' : 'white';
}
}
Loading

0 comments on commit 292ebdb

Please sign in to comment.