Merge pull request 'Live wall: selected incident loads its own calls, resolved deep links, scrubber marks unloaded time (#239)' (#272) from fix/239-call-window into main
This commit was merged in pull request #272.
This commit is contained in:
@@ -11,6 +11,10 @@ export function useCalls(limitCount = 50, dateFrom?: Date, dateTo?: Date) {
|
||||
const [calls, setCalls] = useState<CallRecord[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
// True when the query returned a full page (snap.size, counted BEFORE the
|
||||
// duplicate_of filter below) — there may be older calls past the limit.
|
||||
// calls.length can't answer that: dedup drops rows from a full page.
|
||||
const [hasMore, setHasMore] = useState(false);
|
||||
const { orgId } = useAuth();
|
||||
|
||||
// Stable ms values so the effect dependency doesn't fire on every render
|
||||
@@ -63,6 +67,7 @@ export function useCalls(limitCount = 50, dateFrom?: Date, dateTo?: Date) {
|
||||
// index alongside the existing org_id/started_at query.
|
||||
.filter((c) => !c.duplicate_of);
|
||||
setCalls(docs);
|
||||
setHasMore(snap.size >= limitCount);
|
||||
setLoading(false);
|
||||
}, (err: FirestoreError) => { console.error("useCalls:", err); setError(err.message); setLoading(false); });
|
||||
});
|
||||
@@ -73,7 +78,7 @@ export function useCalls(limitCount = 50, dateFrom?: Date, dateTo?: Date) {
|
||||
};
|
||||
}, [limitCount, dateFromMs, dateToMs, orgId]);
|
||||
|
||||
return { calls, loading, error };
|
||||
return { calls, loading, error, hasMore };
|
||||
}
|
||||
|
||||
export function useCallsByIncident(incidentId: string | null) {
|
||||
|
||||
@@ -86,14 +86,19 @@ export function useIncidents(limitCount = 100, dateFrom?: Date, dateTo?: Date) {
|
||||
export function useIncident(incidentId: string | null) {
|
||||
const [incident, setIncident] = useState<IncidentRecord | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
// The id the current `incident`/`loading` answer belongs to. On the render
|
||||
// where the id changes the effect hasn't run yet, so `loading` alone would
|
||||
// still read false from the previous id and a caller would flash "not found".
|
||||
const [settledId, setSettledId] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!incidentId) { setLoading(false); return; }
|
||||
setLoading(true);
|
||||
let unsubFirestore: (() => void) | undefined;
|
||||
|
||||
const unsubAuth = onAuthStateChanged(auth, (user) => {
|
||||
if (unsubFirestore) { unsubFirestore(); unsubFirestore = undefined; }
|
||||
if (!user) { setLoading(false); return; }
|
||||
if (!user) { setLoading(false); setSettledId(incidentId); return; }
|
||||
|
||||
const ref = doc(db, "incidents", incidentId);
|
||||
unsubFirestore = onSnapshot(ref, (snap) => {
|
||||
@@ -108,16 +113,19 @@ export function useIncident(incidentId: string | null) {
|
||||
setIncident(null);
|
||||
}
|
||||
setLoading(false);
|
||||
setSettledId(incidentId);
|
||||
}, (err: FirestoreError) => {
|
||||
console.error("useIncident:", err);
|
||||
setIncident(null); // a denied/failed read must not leave the previous id's doc
|
||||
setLoading(false);
|
||||
setSettledId(incidentId);
|
||||
});
|
||||
});
|
||||
|
||||
return () => { unsubAuth(); if (unsubFirestore) unsubFirestore(); };
|
||||
}, [incidentId]);
|
||||
|
||||
return { incident, loading };
|
||||
return { incident, loading: loading || (!!incidentId && settledId !== incidentId) };
|
||||
}
|
||||
|
||||
export function useActiveIncidents() {
|
||||
|
||||
Reference in New Issue
Block a user