From e445d8d6d5a0f2bd2d307a398890103cde0cde6e Mon Sep 17 00:00:00 2001 From: Matt DiMeglio Date: Sat, 19 Apr 2025 02:36:25 -0400 Subject: [PATCH] Select call from list of calls --- app/incidents.jsx | 206 ++++++++++++++++++++++-------- app/landing.jsx | 48 +------ hooks/useCallFeed/useCallFeed.jsx | 57 ++++++++- 3 files changed, 218 insertions(+), 93 deletions(-) diff --git a/app/incidents.jsx b/app/incidents.jsx index d952f85..31201d9 100644 --- a/app/incidents.jsx +++ b/app/incidents.jsx @@ -1,12 +1,16 @@ import React, { useState, useRef, useEffect } from 'react'; import styled from 'styled-components'; import { useCallFeed } from '../hooks/useCallFeed'; +import { router } from 'expo-router'; import { Platform, Linking, View, ScrollView, Text, TouchableOpacity } from 'react-native'; +import { StatusBar } from 'expo-status-bar'; +import { SafeAreaView } from 'react-native-safe-area-context'; import { PageHeader, PageFooter, } from '../components/generalHelpers.jsx'; import { Ionicons } from '@expo/vector-icons'; +import { AccidentAndEmergency } from "healthicons-react-native/dist/outline"; import ActionSheet from 'react-native-actions-sheet'; const DepartmentActionSheet = styled(ActionSheet)``; @@ -20,8 +24,18 @@ export default function Incidents() { callIconMap, callDetails, callColorSelector, + formatCallTimePast, + formatCallDateTime } = callFeed; + const sortedAndFilteredCalls = callDetails + .sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp)) + .filter((item, index, self) => { + return index === self.findIndex(i => { + return `${i?.data?.Incident?.IncID}${i?.data?.Response?.ServiceName}` === `${item?.data?.Incident?.IncID}${item?.data?.Response?.ServiceName}` + }); + }); + const { departmentTypeMap, accountDetails, @@ -33,55 +47,6 @@ export default function Incidents() { selectedDepartmentColorPicker, } = departments; - const { Incident, Address, Person, Response } = callDetails; - const { CallThemes, InitList } = accountDetails; - const { - IncID, - IncNumber, - JurisdictionNumber, - ServiceNumber, - ServiceID, - IncDate, - IncNature, - IncNatureCode, - IncNatureCodeDesc, - Notes, - Status, - Origin, - } = Incident; - const { - StreetAddress, - AddressApartment, - Town, - State, - ZipCode, - Latitude, - Longitude, - County, - Intersection1, - Intersection2, - LocationName, - WeatherCondition, - } = Address; - const { - Name, - Age, - Gender, - Statement, - Conscious, - Breathing, - CallBackNumber, - } = Person; - const { - Units - } = Response; - const { - CriticalCallList, - HighCallList, - MediumCallList, - LowCallList, - } = CallThemes; - return ( @@ -123,7 +88,148 @@ export default function Incidents() { - + + + + {sortedAndFilteredCalls?.length ? ( + sortedAndFilteredCalls?.map((callItem, index) => { + const { data: call, timestamp } = callItem; + const { Incident, Response } = call; + const { + ServiceNumber, + IncDate, + IncNature, + IncNatureCode, + IncNatureCodeDesc, + Status, + } = Incident; + const { + ServiceName + } = Response; + const SelectedIcon = callIconMap[IncNature] || AccidentAndEmergency; + return ( + { + router.push({ + pathname: '/landing', + params: { + callDetails: btoa(JSON.stringify(call)) + } + }) + }} + > + + + + {formatCallDateTime(IncDate)} + + {formatCallTimePast(IncDate)} + {Status !== 'CLOSED' ? ( + + ) : null} + + + + + + + {`${IncNature}`} + + + + {`${IncNatureCodeDesc}`} + + + + + + + + + + + + Service: {ServiceName} + + + {`Incident #: ${ServiceNumber}`} + + + + + + ) + })) : ( + There are no Calls + ) } + { - const initDate = new Date(callValue); - const currentTime = new Date(); - - const timeDifference = currentTime - initDate; - - const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24)); - const hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); - const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60)); - const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000); - if (days && days !== 0) { - return `${days} day${days === 1 ? '' : 's'} ago`; - } else if (hours && hours !== 0) { - return `${hours} hour${hours === 1 ? '' : 's'} ago`; - } else if (minutes && minutes !== 0) { - return `${minutes} minute${minutes === 1 ? '' : 's'} ago`; - } else if (seconds && seconds !== 0) { - return `${seconds} second${seconds === 1 ? '' : 's'} ago`; - } - return `Unknown Time Past`; - } - - const formatCallDateTime = (callValue) => { - const initDate = new Date(callValue); - if (initDate) { - const formattedDate = `${initDate.toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - year: 'numeric', - })}`; - const hours = initDate.getHours().toString().padStart(2, '0'); - const minutes = initDate.getMinutes().toString().padStart(2, '0'); - const formattedTime = `${hours}:${minutes}`; - - return `${formattedDate} - ${formattedTime}`; - } - return 'Date Unavailable'; - } - const formatResponseTimes = (time) => { if (time === null) { return ''; diff --git a/hooks/useCallFeed/useCallFeed.jsx b/hooks/useCallFeed/useCallFeed.jsx index be8eeee..3d50f1d 100644 --- a/hooks/useCallFeed/useCallFeed.jsx +++ b/hooks/useCallFeed/useCallFeed.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useDepartments } from '../useDepartments'; -import { Cardiology, Cpr, FourByFour } from "healthicons-react-native/dist/outline"; +import { C, Cardiology, Cpr, FourByFour } from "healthicons-react-native/dist/outline"; +import { useWebSocketContext } from '../useWebSocketContext'; const callIconMap = { "CHEST PAIN|HEART PROBLEMS": Cardiology, @@ -149,8 +150,49 @@ const callDetails = { } } +const formatCallTimePast = (callValue) => { + const initDate = new Date(callValue); + const currentTime = new Date(); + + const timeDifference = currentTime - initDate; + + const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24)); + const hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000); + if (days && days !== 0) { + return `${days} day${days === 1 ? '' : 's'} ago`; + } else if (hours && hours !== 0) { + return `${hours} hour${hours === 1 ? '' : 's'} ago`; + } else if (minutes && minutes !== 0) { + return `${minutes} minute${minutes === 1 ? '' : 's'} ago`; + } else if (seconds && seconds !== 0) { + return `${seconds} second${seconds === 1 ? '' : 's'} ago`; + } + return `Unknown Time Past`; +} + +const formatCallDateTime = (callValue) => { + const initDate = new Date(callValue); + if (initDate) { + const formattedDate = `${initDate.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric', + })}`; + const hours = initDate.getHours().toString().padStart(2, '0'); + const minutes = initDate.getMinutes().toString().padStart(2, '0'); + const formattedTime = `${hours}:${minutes}`; + + return `${formattedDate} - ${formattedTime}`; + } + return 'Date Unavailable'; +} + export const useCallFeed = () => { const departments = useDepartments(); + const { lastMessage } = useWebSocketContext(); + const [allCalls, setAllCalls] = useState([]); const { CallThemes } = departments?.accountDetails; const { CriticalCallList, @@ -159,6 +201,15 @@ export const useCallFeed = () => { LowCallList, } = CallThemes; + useEffect(() => { + if (lastMessage) { + const parsedMessage = JSON?.parse(lastMessage); + if (parsedMessage?.data) { + setAllCalls([...allCalls, parsedMessage]); + } + } + }, [lastMessage]); + const callColorSelector = (callAcuity, cardiacArrestCall, status) => { if (status === 'CLOSED') { return '#0000CD'; @@ -177,7 +228,9 @@ export const useCallFeed = () => { return { departments, callIconMap, - callDetails, + callDetails: allCalls, callColorSelector, + formatCallTimePast, + formatCallDateTime } } \ No newline at end of file