gpt-engineer-app[bot] commited on
Commit
4b1a8d8
·
1 Parent(s): 25811ad
Files changed (1) hide show
  1. src/routes/dashboard.index.tsx +52 -45
src/routes/dashboard.index.tsx CHANGED
@@ -74,59 +74,66 @@ function IncidentsPage() {
74
 
75
  return (
76
  <>
77
- <header className="h-16 border-b border-border flex items-center justify-between px-8 bg-surface/40 backdrop-blur">
78
- <div>
79
  <div className="text-[10px] uppercase tracking-widest text-muted-foreground font-mono">Operations</div>
80
  <h1 className="text-lg font-semibold">Incident Bot</h1>
81
  </div>
82
- <UploadDialog onCreated={(id) => setSelectedId(id)} />
83
- </header>
84
-
85
- <div className="flex-1 grid grid-cols-1 lg:grid-cols-[340px_1fr] min-h-0">
86
- {/* Incident list */}
87
- <div className="border-r border-border flex flex-col min-h-0">
88
- <div className="px-5 py-3 border-b border-border flex items-center justify-between">
89
- <h2 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Feed ({incidents.length})</h2>
90
- <button onClick={load} className="text-muted-foreground hover:text-foreground"><RefreshCw className="h-3.5 w-3.5"/></button>
91
- </div>
92
- <ScrollArea className="flex-1">
93
- <div className="p-3 space-y-2">
94
- {loading ? (
95
- <div className="text-center py-12 text-muted-foreground"><Loader2 className="h-5 w-5 animate-spin mx-auto"/></div>
96
- ) : incidents.length === 0 ? (
97
- <EmptyHint />
98
- ) : incidents.map((i) => (
99
- <button
100
- key={i.id}
101
- onClick={() => setSelectedId(i.id)}
102
- className={cn(
103
- "w-full text-left p-3 rounded-lg border transition-colors group",
104
- selectedId === i.id
105
- ? "bg-surface-elevated border-primary/50 shadow-[var(--shadow-glow)]"
106
- : "bg-surface border-border hover:border-primary/30"
107
- )}
108
- >
109
- <div className="flex items-start justify-between gap-2 mb-1.5">
110
- <span className="font-medium text-sm leading-tight line-clamp-2">{i.title}</span>
111
- <SeverityBadge severity={i.severity} />
112
- </div>
113
- <div className="flex items-center gap-2 text-[10px] text-muted-foreground font-mono uppercase">
114
  <StatusDot status={i.status} />
115
- <span>{i.status}</span>
116
- <span>·</span>
117
- <span>{new Date(i.created_at).toLocaleString()}</span>
 
118
  </div>
119
- </button>
120
  ))}
121
- </div>
122
- </ScrollArea>
 
 
 
 
123
  </div>
 
124
 
125
- {/* Detail */}
126
- <ScrollArea className="bg-background">
127
- {selected ? <IncidentDetail incident={selected} onRerun={() => rerun(selected.id)} onDelete={() => remove(selected.id)} /> : <DetailEmpty />}
128
- </ScrollArea>
129
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
130
  </>
131
  );
132
  }
 
74
 
75
  return (
76
  <>
77
+ <header className="border-b border-border px-8 py-4 bg-surface/40 backdrop-blur flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
78
+ <div className="min-w-0">
79
  <div className="text-[10px] uppercase tracking-widest text-muted-foreground font-mono">Operations</div>
80
  <h1 className="text-lg font-semibold">Incident Bot</h1>
81
  </div>
82
+ <div className="flex items-center gap-2 w-full sm:w-auto">
83
+ <Select
84
+ value={selectedId ?? undefined}
85
+ onValueChange={(v) => setSelectedId(v)}
86
+ disabled={loading || incidents.length === 0}
87
+ >
88
+ <SelectTrigger className="w-full sm:w-[320px]">
89
+ <SelectValue
90
+ placeholder={
91
+ loading
92
+ ? "Loading reports…"
93
+ : incidents.length === 0
94
+ ? "No reports yet"
95
+ : `Select report (${incidents.length})`
96
+ }
97
+ />
98
+ </SelectTrigger>
99
+ <SelectContent className="max-h-[60vh]">
100
+ {incidents.map((i) => (
101
+ <SelectItem key={i.id} value={i.id}>
102
+ <div className="flex items-center gap-2 min-w-0">
 
 
 
 
 
 
 
 
 
 
 
103
  <StatusDot status={i.status} />
104
+ <span className="truncate max-w-[220px]">{i.title}</span>
105
+ <span className="text-[10px] uppercase tracking-wider text-muted-foreground font-mono shrink-0">
106
+ {i.severity}
107
+ </span>
108
  </div>
109
+ </SelectItem>
110
  ))}
111
+ </SelectContent>
112
+ </Select>
113
+ <Button variant="ghost" size="icon" onClick={load} aria-label="Refresh feed">
114
+ <RefreshCw className="h-4 w-4" />
115
+ </Button>
116
+ <UploadDialog onCreated={(id) => setSelectedId(id)} />
117
  </div>
118
+ </header>
119
 
120
+ <ScrollArea className="flex-1 bg-background">
121
+ {loading ? (
122
+ <div className="py-24 text-center text-muted-foreground">
123
+ <Loader2 className="h-5 w-5 animate-spin mx-auto" />
124
+ </div>
125
+ ) : incidents.length === 0 ? (
126
+ <EmptyHint />
127
+ ) : selected ? (
128
+ <IncidentDetail
129
+ incident={selected}
130
+ onRerun={() => rerun(selected.id)}
131
+ onDelete={() => remove(selected.id)}
132
+ />
133
+ ) : (
134
+ <DetailEmpty />
135
+ )}
136
+ </ScrollArea>
137
  </>
138
  );
139
  }