Skip to content

Commit a1f65e7

Browse files
committed
feat: add pulse notification on parked calls
1 parent 3e2c638 commit a1f65e7

File tree

7 files changed

+74
-24
lines changed

7 files changed

+74
-24
lines changed

src/main/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ async function checkForUpdate() {
495495
}
496496

497497
function checkData(data: any): boolean {
498+
log({ data })
498499
return data.hasOwnProperty('account') &&
499500
data.hasOwnProperty('auth') &&
500501
data.hasOwnProperty('theme') &&

src/renderer/src/components/Modules/NethVoice/Parking/ParkedCall.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { isEmpty } from "lodash";
1212
import { useAccount } from "@renderer/hooks/useAccount";
1313
import { useStoreState } from "@renderer/store";
1414
import { useLoggedNethVoiceAPI } from "@renderer/hooks/useLoggedNethVoiceAPI";
15+
import classNames from "classnames";
1516

1617
export interface ParkingCallProps {
1718
parkingDetails: ParkingType,
@@ -25,14 +26,15 @@ export const ParkedCall = ({ parkingDetails, onPickup }: ParkingCallProps) => {
2526
useEffect(() => {
2627
const interval = setInterval(() => {
2728
setTime((prevTime) => {
28-
if (prevTime === Math.ceil(parkingDetails.timeout / 2)) {
29+
if (prevTime <= Math.ceil(parkingDetails.timeout / 2)) {
2930
setStatus('middle');
3031
}
31-
if (prevTime === Math.ceil(parkingDetails.timeout / 4)) {
32+
if (prevTime <= Math.ceil(parkingDetails.timeout / 4)) {
3233
setStatus('end');
3334
}
34-
if (prevTime === 0) {
35+
if (prevTime <= 0) {
3536
clearInterval(interval);
37+
return 0
3638
}
3739
return prevTime - 1;
3840
});
@@ -75,7 +77,7 @@ export const ParkedCall = ({ parkingDetails, onPickup }: ParkingCallProps) => {
7577
}
7678

7779
return (
78-
<div className="relative flex flex-row justify-between items-center min-h-[44px] py-2 text-titleLight dark:text-titleDark">
80+
<div className="relative flex flex-row justify-between items-center min-h-[44px] py-2 ">
7981
<div className="flex flex-col gap-0">
8082
<div className="flex flex-row items-center text-sm text-textYellowLight dark:text-textYellowDark gap-2">
8183
<FontAwesomeIcon size="1x" icon={ParkedCallIcon} className="text-[14px]" />
@@ -100,12 +102,12 @@ export const ParkedCall = ({ parkingDetails, onPickup }: ParkingCallProps) => {
100102
</div>
101103
<div>
102104
<span
103-
className={`${status === 'begin'
105+
className={classNames(status === 'begin'
104106
? 'text-titleLight dark:text-titleDark'
105107
: status === 'middle'
106108
? 'text-amber-700 dark:text-amber-500'
107-
: 'text-red-700 dark:text-red-500'
108-
} w-12 font-mono`}
109+
: 'text-red-700 dark:text-red-500',
110+
'w-12 font-mono')}
109111
>
110112
{formattedTime}
111113
</span>

src/renderer/src/components/Modules/NethVoice/Parking/ParkingBox.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ export const ParkingBox = () => {
3333
if (!isEmpty(parkingObjectInformations)) {
3434
try {
3535
await NethVoiceAPI.AstProxy.pickupParking(parkingObjectInformations)
36-
//store.dispatch.park.setParkingCallTaken(true)
37-
// retrieveParksList()
3836
} catch (error) {
3937
console.error(error)
4038
}

src/renderer/src/components/Modules/NethVoice/Parking/hook/useParkingModule.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { useStoreState } from "@renderer/store"
22
import { ParkingType } from "@shared/types"
3+
import { log } from "@shared/utils/logger"
4+
import { difference, differenceBy, differenceWith } from "lodash"
35
import { useEffect, useState } from "react"
46

57
export const useParkingModule = () => {
@@ -10,13 +12,16 @@ export const useParkingModule = () => {
1012
parkedCalls && extractValidParkedCalls(parkedCalls)
1113
}, [parkedCalls])
1214

15+
1316
const extractValidParkedCalls = (parkedCalls: ParkingType[]) => {
1417
setValidParkedCalls(() => [
1518
...(parkedCalls?.filter((p) => !!p.parkedCaller.name) || [])
16-
])
19+
]
20+
)
1721
}
1822

23+
1924
return {
20-
parkedCalls: validParkedCalls
25+
parkedCalls: validParkedCalls,
2126
}
2227
}

src/renderer/src/components/Sidebar.tsx

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import { useStoreState } from '@renderer/store'
1010
import { CallData, NethLinkPageData, NotificationData, ParkingType } from '@shared/types'
1111
import { MENU_ELEMENT, PERMISSION } from '@shared/constants'
1212
import { useAccount } from '@renderer/hooks/useAccount'
13+
import { useParkingModule } from './Modules/NethVoice/Parking/hook/useParkingModule'
14+
import { log } from '@shared/utils/logger'
15+
import { difference } from 'lodash'
1316

1417
export interface SidebarProps {
1518
onChangeMenu: (menuElement: MENU_ELEMENT) => void
@@ -19,9 +22,14 @@ export function Sidebar({ onChangeMenu }: SidebarProps): JSX.Element {
1922

2023
const [nethLinkPageData, setNethLinkPageData] = useStoreState<NethLinkPageData>('nethLinkPageData')
2124
const [missedCalls] = useStoreState<CallData[]>('missedCalls')
22-
const [parkedCalls] = useStoreState<ParkingType[]>('parkings')
2325
const [notifications] = useStoreState<NotificationData>('notifications')
26+
const [lastMenu, setLastMenu] = useState<MENU_ELEMENT>(MENU_ELEMENT.SPEEDDIALS)
27+
28+
const viewedParkedCalls = useRef<ParkingType[]>([])
29+
const [parkedPulse, setParkedPulse] = useState<boolean>(false)
30+
2431
const { hasPermission } = useAccount()
32+
const { parkedCalls } = useParkingModule()
2533
function handleSidebarMenuSelection(menuElement: MENU_ELEMENT): void {
2634
setNethLinkPageData((p) => ({
2735
...p,
@@ -34,11 +42,26 @@ export function Sidebar({ onChangeMenu }: SidebarProps): JSX.Element {
3442
}
3543

3644
useEffect(() => {
37-
if (nethLinkPageData && nethLinkPageData.selectedSidebarMenu) {
45+
if (nethLinkPageData && nethLinkPageData.selectedSidebarMenu && lastMenu !== nethLinkPageData.selectedSidebarMenu) {
46+
setLastMenu(() => nethLinkPageData.selectedSidebarMenu)
3847
onChangeMenu(nethLinkPageData.selectedSidebarMenu)
3948
}
4049
}, [nethLinkPageData?.selectedSidebarMenu])
4150

51+
52+
useEffect(() => {
53+
if (nethLinkPageData?.selectedSidebarMenu === MENU_ELEMENT.PARKED_CALLS) {
54+
viewedParkedCalls.current = [...(parkedCalls || [])]
55+
}
56+
const currentNames = parkedCalls?.map((c) => c.parkedCaller.name) || []
57+
viewedParkedCalls.current = viewedParkedCalls.current.filter((p) => currentNames.includes(p.parkedCaller.name))
58+
const names = viewedParkedCalls.current.map((c) => c.parkedCaller.name)
59+
const diff = difference(currentNames, names)
60+
if (diff.length > 0) {
61+
setParkedPulse(true)
62+
}
63+
}, [parkedCalls, nethLinkPageData?.selectedSidebarMenu])
64+
4265
return (
4366
<div className="flex flex-col h-full max-w-[50px] justify-between pt-3 pb-2 px-2 border-0 border-l-[1px] dark:border-borderDark border-borderLight">
4467
<div className="flex flex-col items-center gap-6">
@@ -64,8 +87,12 @@ export function Sidebar({ onChangeMenu }: SidebarProps): JSX.Element {
6487
<SidebarButton
6588
icon={ParkedCallMenuIcon}
6689
focus={nethLinkPageData?.selectedSidebarMenu === MENU_ELEMENT.PARKED_CALLS}
67-
hasNotification={false}
68-
onClick={() => handleSidebarMenuSelection(MENU_ELEMENT.PARKED_CALLS)}
90+
hasNotification={(parkedCalls?.length || 0) > 0}
91+
hasPulseNotification={parkedPulse}
92+
onClick={() => {
93+
handleSidebarMenuSelection(MENU_ELEMENT.PARKED_CALLS)
94+
setParkedPulse(false)
95+
}}
6996
isSelected={nethLinkPageData?.selectedSidebarMenu === MENU_ELEMENT.PARKED_CALLS}
7097
/>
7198
)

src/renderer/src/components/SidebarButton.tsx

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface SidebarButtonProps {
1010
isSelected?: boolean
1111
className?: string
1212
hasNotification?: boolean
13+
hasPulseNotification?: boolean
1314
onClick?: () => void
1415
}
1516
export function SidebarButton({
@@ -19,6 +20,7 @@ export function SidebarButton({
1920
isSelected,
2021
notificable,
2122
hasNotification,
23+
hasPulseNotification,
2224
onClick
2325
}: SidebarButtonProps): JSX.Element {
2426
return (
@@ -46,18 +48,30 @@ export function SidebarButton({
4648
<FontAwesomeIcon size="1x" icon={icon} className="text-[20px]" />
4749
</div>
4850
{hasNotification && (
49-
<div
50-
className={classNames(`
51-
absolute top-[1px] left-[1px]
52-
w-3 h-3
53-
dark:bg-textBlueDark bg-textBlueLight
54-
rounded-full
55-
border-2 `,
51+
<div className='absolute top-[1px] left-[1px] flex justify-center items-center'>
52+
<div className={classNames(`
53+
w-3 h-3
54+
dark:bg-textRedDark bg-textRedLight
55+
56+
rounded-full
57+
border-2 `,
5658
focus
5759
? 'dark:border-hoverDark border-hoverLight'
5860
: 'dark:border-bgDark border-bgLight dark:group-hover:border-hoverDark group-hover:border-hoverLight'
59-
)}
60-
/>
61+
)}>
62+
63+
</div>
64+
{!focus && hasPulseNotification &&
65+
<div
66+
className={classNames(`
67+
absolute
68+
w-2.5 h-2.5
69+
dark:bg-textRedDark bg-textRedLight
70+
rounded-full
71+
animate-ping
72+
`)}
73+
/>}
74+
</div>
6175
)}
6276
</div>
6377
</div>

tailwind.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export default {
3434
//yellow text
3535
textYellowLight: '#B45309', //yellow-700
3636
textYellowDark: '#F59E0B', // yellow-500
37+
//red text
38+
textRedLight: '#BE123C', //red-700
39+
textRedDark: '#F43F5E', // red-500
3740

3841
//amber icon
3942
iconAmberLight: '#b45309', //amber-700

0 commit comments

Comments
 (0)