Skip to content

Commit

Permalink
Minor improve to handle Notfication component, make sure call get cre…
Browse files Browse the repository at this point in the history
…dentials only logged in and Add animation on new credentials cards
  • Loading branch information
gkatrakazas committed May 16, 2024
1 parent 4c691b3 commit 6cdb869
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 49 deletions.
3 changes: 1 addition & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function App() {
<Snowfalling />
<Router>
<Suspense fallback={<Spinner />}>
<HandlerNotification>
<HandlerNotification/>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/settings" element={<PrivateRoute><Settings /></PrivateRoute>} />
Expand All @@ -108,7 +108,6 @@ function App() {
{showMessagePopup &&
<MessagePopup type={typeMessagePopup} message={textMessagePopup} onClose={() => setMessagePopup(false)} />
}
</HandlerNotification>
</Suspense>
</Router>
</CredentialsProvider>
Expand Down
11 changes: 4 additions & 7 deletions src/components/HandlerNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ const ToastDisplay = ({ id, notification }) => {
);
};

const HandlerNotification = ({ children }) => {
const HandlerNotification = () => {
const [notification, setNotification] = useState({ title: '', body: '' });
const { refreshCredentials } = useContext(CredentialsContext);
const { getData } = useContext(CredentialsContext);

const showToast = () =>
toast((t) => <ToastDisplay id={t.id} notification={notification} />);
Expand All @@ -50,7 +50,7 @@ const HandlerNotification = ({ children }) => {
title: payload?.notification?.title,
body: payload?.notification?.body,
});
refreshCredentials();
getData();
})
.catch((err) => {
console.log('Failed to receive message:', err);
Expand All @@ -61,13 +61,10 @@ const HandlerNotification = ({ children }) => {
messageListener();
}
};
}, [refreshCredentials]);
}, [getData]);

return (
<div>
<Toaster />
{children}
</div>
);
};

Expand Down
68 changes: 36 additions & 32 deletions src/context/CredentialsContext.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,45 @@
import React, { createContext, useState, useEffect } from 'react';
import React, { createContext, useState, useEffect, useCallback } from 'react';
import { useApi } from '../api';
import { extractCredentialFriendlyName } from '../functions/extractCredentialFriendlyName';

const CredentialsContext = createContext();

export const CredentialsProvider = ({ children }) => {
const api = useApi();
const [vcEntityList, setVcEntityList] = useState([]);

useEffect(() => {
const getData = async () => {
const response = await api.get('/storage/vc');
const vcEntityList = await Promise.all(response.data.vc_list.map(async vcEntity => {
const name = await extractCredentialFriendlyName(vcEntity.credential);
return { ...vcEntity, friendlyName: name };
}));
vcEntityList.sort((vcA, vcB) => vcB.issuanceDate - vcA.issuanceDate);
setVcEntityList(vcEntityList);
};
getData();
}, [api]);

const refreshCredentials = async () => {
const response = await api.get('/storage/vc');
const vcEntityList = await Promise.all(response.data.vc_list.map(async vcEntity => {
const name = await extractCredentialFriendlyName(vcEntity.credential);
return { ...vcEntity, friendlyName: name };
}));
vcEntityList.sort((vcA, vcB) => vcB.issuanceDate - vcA.issuanceDate);
setVcEntityList(vcEntityList);
};

return (
<CredentialsContext.Provider value={{ vcEntityList, refreshCredentials }}>
{children}
</CredentialsContext.Provider>
);
const api = useApi();
const [vcEntityList, setVcEntityList] = useState([]);
const [latestCredentials, setLatestCredentials] = useState(new Set());

const getData = useCallback(async () => {
try {
const response = await api.get('/storage/vc');
const fetchedVcList = response.data.vc_list;
const vcEntityList = await Promise.all(fetchedVcList.map(async vcEntity => {
const name = await extractCredentialFriendlyName(vcEntity.credential);
return { ...vcEntity, friendlyName: name };
}));
vcEntityList.sort((vcA, vcB) => new Date(vcB.issuanceDate) - new Date(vcA.issuanceDate));

const latestIssuanceDate = vcEntityList[0]?.issuanceDate;
const latestCreds = new Set(vcEntityList.filter(vc => vc.issuanceDate === latestIssuanceDate).map(vc => vc.id));

if (window.location.pathname.includes('/cb')) {
setLatestCredentials(latestCreds);
setTimeout(() => {
setLatestCredentials(new Set());
}, 8000); // Clear the highlight after 5 seconds
}

setVcEntityList(vcEntityList);
} catch (error) {
console.error('Failed to fetch data', error);
}
}, [api]);

return (
<CredentialsContext.Provider value={{ vcEntityList, latestCredentials, getData }}>
{children}
</CredentialsContext.Provider>
);
};

export default CredentialsContext;
29 changes: 29 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,32 @@ button.reactour__close {
top: 12px;
right: 12px;
}

/* Animations for new credentials */
@keyframes highlight-filter {
0%, 100% {
filter: brightness(1);
}
50% {
filter: brightness(1.15);
}
}

@keyframes fade-in {
0% {
opacity: 0;
transform: translateY(-300px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}

.highlight-filter {
animation: highlight-filter 5s ease-in-out;
}

.fade-in {
animation: fade-in 1s ease-in-out;
}
18 changes: 10 additions & 8 deletions src/pages/Home/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import CredentialsContext from '../../context/CredentialsContext';

const Home = () => {
const api = useApi();
const { vcEntityList, refreshCredentials } = useContext(CredentialsContext);
const { vcEntityList,latestCredentials, getData } = useContext(CredentialsContext);
const [isSmallScreen, setIsSmallScreen] = useState(window.innerWidth < 768);
const [currentSlide, setCurrentSlide] = useState(1);
const [showFullscreenImgPopup, setShowFullscreenImgPopup] = useState(false);
Expand All @@ -51,6 +51,10 @@ const Home = () => {
style: { margin: '0 10px' },
};

useEffect(() => {
getData();
}, [getData]);

useEffect(() => {
const handleResize = () => {
setIsSmallScreen(window.innerWidth < 768);
Expand Down Expand Up @@ -86,7 +90,7 @@ const Home = () => {
setLoading(true);
try {
await api.del(`/storage/vc/${selectedVcEntity.credentialIdentifier}`);
await refreshCredentials();
await getData();
} catch (error) {
console.error('Failed to delete data', error);
}
Expand Down Expand Up @@ -129,14 +133,12 @@ const Home = () => {
{(currentSlide === index + 1 ? 'button' : 'div')
.split()
.map(Tag => (
<Tag
key={`${vcEntity.id}-${Tag}`}
className="relative rounded-xl xl:w-4/5 md:w-full sm:w-full overflow-hidden transition-shadow shadow-md hover:shadow-lg cursor-pointer w-full mb-2"
<Tag key={vcEntity.id} className={`relative rounded-xl xl:w-4/5 md:w-full sm:w-full overflow-hidden transition-shadow shadow-md hover:shadow-lg cursor-pointer w-full mb-2 ${latestCredentials.has(vcEntity.id) ? 'fade-in' : ''}`}
onClick={() => { setShowFullscreenImgPopup(true); setSelectedVcEntity(vcEntity); }}
aria-label={`${vcEntity.friendlyName}`}
title={t('pageCredentials.credentialFullScreenTitle', { friendlyName: vcEntity.friendlyName })}
>
<CredentialImage credential={vcEntity.credential} className="w-full h-full object-cover rounded-xl" />
<CredentialImage credential={vcEntity.credential} className={`w-full h-full object-cover rounded-xl ${latestCredentials.has(vcEntity.id) ? 'highlight-filter' : ''}`} />
</Tag>
))}
<div className="flex items-center justify-end">
Expand Down Expand Up @@ -176,12 +178,12 @@ const Home = () => {
{vcEntityList.map((vcEntity) => (
<button
key={vcEntity.id}
className="relative rounded-xl overflow-hidden transition-shadow shadow-md hover:shadow-lg cursor-pointer"
className={`relative rounded-xl overflow-hidden transition-shadow shadow-md hover:shadow-lg cursor-pointer ${latestCredentials.has(vcEntity.id) ? 'highlight-border fade-in' : ''}`}
onClick={() => handleImageClick(vcEntity)}
aria-label={`${vcEntity.friendlyName}`}
title={t('pageCredentials.credentialDetailsTitle', { friendlyName: vcEntity.friendlyName })}
>
<CredentialImage credential={vcEntity.credential} className={"w-full h-full object-cover rounded-xl"} />
<CredentialImage credential={vcEntity.credential} className={`w-full h-full object-cover rounded-xl ${latestCredentials.has(vcEntity.id) ? 'highlight-filter' : ''}`} />
</button>
))}
<button
Expand Down

0 comments on commit 6cdb869

Please sign in to comment.