File size: 1,751 Bytes
9d2d895
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Shared formatter for the energy-disruption timeline used by
// PipelineStatusPanel and StorageFacilityMapPanel drawers.
//
// Kept dependency-free (no generated type imports, no DOM) so the panels
// can assemble HTML with their existing escape/sanitize helpers. Both
// drawers call renderDisruptionList on the same shape and get a
// consistent UI.

export interface DisruptionSourceInput {
  authority?: string;
  title?: string;
  url?: string;
  date?: string;
  sourceType?: string;
}

export interface DisruptionEventInput {
  id?: string;
  eventType?: string;
  startAt?: string;
  endAt?: string;
  capacityOfflineBcmYr?: number;
  capacityOfflineMbd?: number;
  causeChain?: ReadonlyArray<string>;
  shortDescription?: string;
  sources?: ReadonlyArray<DisruptionSourceInput>;
}

export function formatEventWindow(start: string | undefined, end: string | undefined): string {
  const startDay = (start || '').slice(0, 10);
  const endDay = (end || '').slice(0, 10);
  if (!startDay) return 'date unknown';
  if (!endDay) return `${startDay} · ongoing`;
  if (endDay === startDay) return startDay;
  return `${startDay}${endDay}`;
}

export function formatCapacityOffline(
  bcmYr: number | undefined,
  mbd: number | undefined,
): string {
  const parts: string[] = [];
  if (typeof bcmYr === 'number' && bcmYr > 0) parts.push(`${bcmYr.toFixed(1)} bcm/yr`);
  if (typeof mbd === 'number' && mbd > 0) parts.push(`${mbd.toFixed(2)} mb/d`);
  return parts.length > 0 ? parts.join(' · ') : '';
}

export type DisruptionStatus = 'ongoing' | 'resolved' | 'unknown';

export function statusForEvent(event: DisruptionEventInput): DisruptionStatus {
  if (!event.startAt) return 'unknown';
  return event.endAt ? 'resolved' : 'ongoing';
}