mirror of
https://github.com/0xWheatyz/handler.git
synced 2026-09-07 12:16:23 +00:00
feat(app): replace mock data with live Handler API
Wire the mobile app to the real Handler API instead of the transcribed prototype data: - src/api/client.ts: typed client ported from frontend/lib/api.ts (bearer auth, AuthError/ApiError, base URL param, allow401 for admin-only resume) - src/api/format.ts: relative-time + status label/tone/color helpers - src/state/ServerConfig.tsx: endpoint+token persisted to AsyncStorage - src/screens/ConnectScreen.tsx: first-open config, validated via /health then /projects - src/state/AppState.tsx: data-driven store polling projects -> agents -> checkmarks -> logs every 10s with per-item failure isolation; derives fleet counts, waiting list, recent checkmarks, merged log; answer+resume, spawn, kill mutations; 401 routes back to ConnectScreen - screens render live data; detail meta is Started/Status/Tests/Build; Pause removed (no endpoint); Kill confirms; log filters are per-project - delete src/data/mock.ts tsc clean; Hermes bundle builds (200).
This commit is contained in:
@@ -6,22 +6,22 @@ import { useTheme } from "../theme/useTheme";
|
||||
import { Chip } from "../components/Chip";
|
||||
import { Mono, SectionLabel } from "../components/primitives";
|
||||
import { TabBar } from "../components/TabBar";
|
||||
import { useAppState, type LogFilter } from "../state/AppState";
|
||||
import { allLog } from "../data/mock";
|
||||
|
||||
const FILTERS: { key: LogFilter; label: string }[] = [
|
||||
{ key: "all", label: "All" },
|
||||
{ key: "handler", label: "handler" },
|
||||
{ key: "errors", label: "Errors" },
|
||||
];
|
||||
import { useAppState } from "../state/AppState";
|
||||
import { clockTime, statusColor } from "../api/format";
|
||||
|
||||
export function LogScreen() {
|
||||
const { colors } = useTheme();
|
||||
const insets = useSafeAreaInsets();
|
||||
const { logFilter, setLogFilter } = useAppState();
|
||||
const { logFilter, setLogFilter, globalLog, projects } = useAppState();
|
||||
|
||||
const entries = allLog.filter((e) =>
|
||||
logFilter === "all" ? true : logFilter === "errors" ? e.err : e.p === "handler"
|
||||
const filters: { key: string; label: string }[] = [
|
||||
{ key: "all", label: "All" },
|
||||
...projects.map((p) => ({ key: p.id, label: p.id })),
|
||||
{ key: "errors", label: "Errors" },
|
||||
];
|
||||
|
||||
const entries = globalLog.filter((e) =>
|
||||
logFilter === "all" ? true : logFilter === "errors" ? e.err : e.project === logFilter,
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -30,8 +30,12 @@ export function LogScreen() {
|
||||
|
||||
<View style={styles.header}>
|
||||
<Text style={[text.h3, { color: colors.textHeading }]}>Log</Text>
|
||||
<View style={styles.filters}>
|
||||
{FILTERS.map((f) => (
|
||||
<ScrollView
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={styles.filters}
|
||||
>
|
||||
{filters.map((f) => (
|
||||
<Chip
|
||||
key={f.key}
|
||||
label={f.label}
|
||||
@@ -39,11 +43,11 @@ export function LogScreen() {
|
||||
onPress={() => setLogFilter(f.key)}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
<View style={styles.todayLabel}>
|
||||
<SectionLabel>Today</SectionLabel>
|
||||
<SectionLabel>Activity</SectionLabel>
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
@@ -54,17 +58,26 @@ export function LogScreen() {
|
||||
]}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{entries.map((e, i) => (
|
||||
<View key={`${e.t}-${i}`} style={styles.logRow}>
|
||||
<Mono style={[styles.mono, { color: colors.ink4 }]}>{e.t}</Mono>
|
||||
<Mono style={[styles.mono, styles.idCol, { color: colors.ink6 }]}>
|
||||
{e.id}
|
||||
</Mono>
|
||||
<Mono style={[styles.mono, { color: colors[e.color], flex: 1 }]}>
|
||||
{e.msg}
|
||||
</Mono>
|
||||
</View>
|
||||
))}
|
||||
{entries.length === 0 ? (
|
||||
<Text style={[text.bodySm, { color: colors.textMuted }]}>No activity yet.</Text>
|
||||
) : (
|
||||
entries.map((e) => (
|
||||
<View key={e.key} style={styles.logRow}>
|
||||
<Mono style={[styles.mono, { color: colors.ink4 }]}>
|
||||
{clockTime(e.createdAt)}
|
||||
</Mono>
|
||||
<Mono
|
||||
numberOfLines={1}
|
||||
style={[styles.mono, styles.idCol, { color: colors.ink6 }]}
|
||||
>
|
||||
{e.name}
|
||||
</Mono>
|
||||
<Mono style={[styles.mono, { color: colors[statusColor(e.status)], flex: 1 }]}>
|
||||
{e.msg}
|
||||
</Mono>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</ScrollView>
|
||||
|
||||
<TabBar active="log" />
|
||||
@@ -75,7 +88,7 @@ export function LogScreen() {
|
||||
const styles = StyleSheet.create({
|
||||
page: { flex: 1 },
|
||||
header: { paddingHorizontal: 20, paddingTop: 20, paddingBottom: 16 },
|
||||
filters: { flexDirection: "row", gap: 8, marginTop: 14 },
|
||||
filters: { flexDirection: "row", gap: 8, marginTop: 14, paddingRight: 20 },
|
||||
todayLabel: { paddingHorizontal: 20, paddingBottom: 8 },
|
||||
feed: {
|
||||
borderTopWidth: 1,
|
||||
@@ -85,5 +98,5 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
logRow: { flexDirection: "row", gap: 10 },
|
||||
mono: { fontSize: 12.5, lineHeight: 26 },
|
||||
idCol: { width: 66 },
|
||||
idCol: { width: 86 },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user