Skip to content

Commit

Permalink
Merge pull request #575 from nwplus/announcements
Browse files Browse the repository at this point in the history
new announcements
  • Loading branch information
alvinkam33 authored Mar 9, 2024
2 parents 5665a70 + 5d659c7 commit 0059982
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 19 deletions.
49 changes: 30 additions & 19 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,9 @@ import ThemeProvider from './theme/ThemeProvider'
import { AuthProvider, getRedirectUrl, useAuth } from './utility/Auth'
import { APPLICATION_STATUS, DB_COLLECTION, DB_HACKATHON, IS_DEVICE_IOS } from './utility/Constants'
import { HackerApplicationProvider, useHackerApplication } from './utility/HackerApplicationContext'
import { db, getLivesiteDoc } from './utility/firebase'
import { db, getAnnouncement, getLivesiteDoc } from './utility/firebase'
import notifications from './utility/notifications'

// only notify user if announcement was created within last 5 secs
const notifyUser = announcement => {
const isRecent = new Date() - new Date(announcement.timestamp) < 5000
if (isRecent && notifications.areEnabled()) {
notifications.trigger('New Announcement', announcement.content)
}
}
import AnnouncementToast from './components/AnnouncementToast'

const PageRoute = ({ path, children }) => {
const [livesiteDoc, setLivesiteDoc] = useState(null)
Expand Down Expand Up @@ -167,25 +160,42 @@ const ApplicationDashboardRoutingContainer = () => {
}

function App() {
const [announcements, setAnnouncements] = useState([])
// const [announcements, setAnnouncements] = useState([])
const [announcementText, setAnnouncementText] = useState('')

const notifyUser = async announcementId => {
// grab announcement from firebase to check if removed, if doesn't exist anymore don't send
const announcement = await getAnnouncement(announcementId)
if (!announcement) return
// only notify user if announcement is scheduled within last 5 secs
const isRecent = new Date() - new Date(announcement.announcementTime) < 5000
if (isRecent) {
// don't notify users on IOS devices because Notification API incompatible
if (!IS_DEVICE_IOS) {
notifications.trigger('New Announcement', announcement.content)
}
setAnnouncementText(announcement.content)
}
}

useEffect(() => {
const unsubscribe = db
.collection(DB_COLLECTION)
.doc(DB_HACKATHON)
.collection('Announcements')
.orderBy('timestamp', 'desc')
.limit(6)
.onSnapshot(querySnapshot => {
setAnnouncements(Object.values(querySnapshot.docs.map(doc => doc.data())))
// firebase doc that triggered db change event
const changedDoc = querySnapshot.docChanges()[0]

const docChanges = querySnapshot.docChanges()
const changedDoc = docChanges[0]
const id = changedDoc?.doc.id
const announcement = changedDoc?.doc.data()
// don't want to notify on 'remove' + 'modified' db events
if (changedDoc && changedDoc.type === 'added') {
// don't notify users on IOS devices because Notification API incompatible
if (!IS_DEVICE_IOS) {
notifyUser(changedDoc.doc.data())
if (changedDoc?.type === 'added') {
if (announcement.type === 'immediate') {
notifyUser(id)
} else if (announcement.type === 'scheduled') {
setTimeout(() => notifyUser(id), new Date(announcement.announcementTime) - new Date())
}
}
})
Expand All @@ -196,9 +206,10 @@ function App() {
<ThemeProvider>
<AuthProvider>
<GlobalStyle />
<AnnouncementToast text={announcementText} />
<Switch>
<PageRoute path="/">
<Home announcements={announcements} />
<Home />
</PageRoute>
<PageRoute path="/charcuterie">
<Charcuterie />
Expand Down
4 changes: 4 additions & 0 deletions src/assets/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
97 changes: 97 additions & 0 deletions src/components/AnnouncementToast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { useEffect, useState } from 'react'
import styled from 'styled-components'
import CloseIcon from '../assets/close.svg'

const ToastBackground = styled.div`
width: 100%;
height: 100%;
position: fixed;
backdrop-filter: blur(3px);
display: ${p => (p.shown ? 'block' : 'none')};
z-index: 999;
`
const ToastDiv = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
width: 90%;
border: none;
outline: none;
background: linear-gradient(92.58deg, #0defe1 0%, #78ff96 100%);
position: fixed;
-webkit-text-fill-color: #2c2543;
color: #2c2543;
text-decoration: none;
top: ${p => (p.shown ? '40px' : '-100px')};
transition: margin-top 0.5s ease-in;
margin-left: auto;
margin-right: auto;
padding: 0.5em;
left: 0;
right: 0;
border-radius: 5px;
word-break: break-word;
z-index: 1000;
font-size: 20px;
font-weight: 600;
&:before {
content: '';
position: absolute;
z-index: -1;
inset: 0;
border: 1px solid transparent;
border-radius: 5px;
background: inherit;
background-origin: border-box;
background-clip: border-box;
-webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
-webkit-mask-repeat: no-repeat;
}
`

const Icon = styled.span`
margin: 0 4px;
-webkit-text-fill-color: red;
color: red;
`

const ToastText = styled.div`
padding: 0 8px;
flex: 1;
`

const CloseButton = styled.button`
background: none;
border: none;
cursor: pointer;
`

export default function AnnouncementToast({ text }) {
const [showToast, setShowToast] = useState(false)

useEffect(() => {
if (text) {
setShowToast(true)
} else {
setShowToast(false)
}
}, [text])

return (
<>
<ToastBackground shown={showToast} />
<ToastDiv key={text} shown={showToast}>
<div>
<Icon>&#8252;</Icon>ANNOUNCEMENT<Icon>&#8252;</Icon>
</div>
<ToastText>{text}</ToastText>
<CloseButton onClick={() => setShowToast(false)}>
<img src={CloseIcon} alt="Close Button" />
</CloseButton>
</ToastDiv>
</>
)
}
8 changes: 8 additions & 0 deletions src/utility/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const livesiteDocRef = db.collection('InternalWebsites').doc('Livesite')
export const currentHackathonRef = db.collection(DB_COLLECTION).doc(DB_HACKATHON)
export const applicantsRef = db.collection(DB_COLLECTION).doc(DB_HACKATHON).collection('Applicants')
export const projectsRef = db.collection(DB_COLLECTION).doc(DB_HACKATHON).collection('Projects')
export const announcementsRef = db
.collection(DB_COLLECTION)
.doc(DB_HACKATHON)
.collection('Announcements')

export const getLivesiteDoc = callback => {
return livesiteDocRef.onSnapshot(doc => {
Expand Down Expand Up @@ -190,3 +194,7 @@ export const updateProject = (author, projectId, data) => {
},
})
}

export const getAnnouncement = async announcementId => {
return (await announcementsRef.doc(announcementId).get()).data()
}

0 comments on commit 0059982

Please sign in to comment.