feat: add PDF reports, timezone management, GPS QR codes, and fix GPS tracking gaps
Issue #1: QR button on GPS Devices tab for re-enrollment Issue #2: App-wide timezone setting with TimezoneContext, useFormattedDate hook, and admin timezone selector. All date displays now respect the configured timezone. Issue #3: PDF export for Accountability Roster using @react-pdf/renderer with professional styling matching VIPSchedulePDF. Added Signal send button. Issue #4: Fixed GPS "teleporting" gaps - syncPositions now fetches position history per device instead of only latest position. Changed cron to every 30s, added unique constraint on deviceId+timestamp for deduplication, lowered min interval to 10s. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { X, Send, Loader2 } from 'lucide-react';
|
||||
import { useDriverMessages, useSendMessage, useMarkMessagesAsRead } from '../hooks/useSignalMessages';
|
||||
import { useFormattedDate } from '@/hooks/useFormattedDate';
|
||||
|
||||
interface Driver {
|
||||
id: string;
|
||||
@@ -18,6 +19,7 @@ export function DriverChatModal({ driver, isOpen, onClose }: DriverChatModalProp
|
||||
const [message, setMessage] = useState('');
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null);
|
||||
const { formatDateTime } = useFormattedDate();
|
||||
|
||||
const { data: messages, isLoading } = useDriverMessages(driver?.id || null, isOpen);
|
||||
const sendMessage = useSendMessage();
|
||||
@@ -66,22 +68,6 @@ export function DriverChatModal({ driver, isOpen, onClose }: DriverChatModalProp
|
||||
}
|
||||
};
|
||||
|
||||
const formatTime = (timestamp: string) => {
|
||||
const date = new Date(timestamp);
|
||||
const now = new Date();
|
||||
const isToday = date.toDateString() === now.toDateString();
|
||||
|
||||
if (isToday) {
|
||||
return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
|
||||
}
|
||||
return date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit'
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div
|
||||
@@ -126,7 +112,7 @@ export function DriverChatModal({ driver, isOpen, onClose }: DriverChatModalProp
|
||||
<p className={`text-[10px] mt-1 ${
|
||||
msg.direction === 'OUTBOUND' ? 'text-primary-foreground/70' : 'text-muted-foreground/70'
|
||||
}`}>
|
||||
{formatTime(msg.timestamp)}
|
||||
{formatDateTime(msg.timestamp)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user