import { useEffect, useState } from "react"; import { View, Text, ScrollView, Pressable, Alert, Share, } from "react-native"; import { useLocalSearchParams, router, useNavigation } from "expo-router"; import * as Clipboard from "expo-clipboard"; import * as SecureStore from "expo-secure-store"; import { getIncidentById, updateIncident, deleteIncident, markIncidentPushed } from "@/lib/db"; import { renderMarkdown } from "@/lib/markdown"; import { pushIncidentToGit, loadGitConfig } from "@/lib/git"; import type { Incident } from "@/types/incident"; import { Colors } from "@/constants/theme"; const SECTION_LABEL = { color: Colors.text2, fontSize: 11, fontWeight: "700" as const, textTransform: "uppercase" as const, letterSpacing: 0.8, marginBottom: 6, marginTop: 20, } as const; const SECTION_CONTENT = { color: Colors.text1, fontSize: 14, fontFamily: "monospace", backgroundColor: Colors.surface, borderRadius: 8, padding: 12, lineHeight: 20, } as const; export default function IncidentDetailScreen() { const { id } = useLocalSearchParams<{ id: string }>(); const navigation = useNavigation(); const [incident, setIncident] = useState(null); const [pushing, setPushing] = useState(false); useEffect(() => { if (id) { getIncidentById(id).then((inc) => { setIncident(inc); if (inc) { navigation.setOptions({ title: inc.title || "Incident" }); } }); } }, [id]); async function handleDelete() { if (!incident) return; Alert.alert( "Delete incident?", "This action cannot be undone.", [ { text: "Cancel", style: "cancel" }, { text: "Delete", style: "destructive", onPress: async () => { await deleteIncident(incident.id); router.replace("/"); }, }, ] ); } async function handleResolve() { if (!incident) return; await updateIncident(incident.id, { status: "resolved" }); setIncident({ ...incident, status: "resolved" }); } async function handleGitPush() { if (!incident) return; const [config, template] = await Promise.all([ loadGitConfig(), SecureStore.getItemAsync("md_template"), ]); if (!config) { Alert.alert("Git not configured", "Set up a git provider in Settings first."); return; } setPushing(true); const result = await pushIncidentToGit(incident, config, template ?? undefined); setPushing(false); if (result.success) { const now = new Date().toISOString(); await markIncidentPushed(incident.id); setIncident((prev) => prev ? { ...prev, gitPushedAt: now } : prev); Alert.alert("Pushed", result.url ?? "Push successful."); } else { Alert.alert("Push failed", result.error ?? "Unknown error"); } } async function handleExport() { if (!incident) return; const md = renderMarkdown(incident); try { await Share.share({ message: md, title: incident.title }); } catch { await Clipboard.setStringAsync(md); Alert.alert("Copied", "Markdown copied to clipboard."); } } if (!incident) { return ( Loading… ); } return ( {/* Status badge */} {incident.status} {incident.service ? ( {incident.service} ) : null} {incident.createdAt.slice(0, 16).replace("T", " ")} {incident.title || "Untitled"} {incident.tags.length > 0 && ( {incident.tags.map((tag) => ( {tag} ))} )} Symptom {incident.symptom || "—"} Root Cause {incident.rootCause || "—"} Fix Applied {incident.fix || "—"} {/* Actions */} {incident.status === "open" && ( Mark as Resolved )} Export Markdown {pushing ? "Pushing…" : "Push to Git"} router.push({ pathname: "/new", params: { editId: incident.id } })} style={{ backgroundColor: Colors.surface, borderWidth: 1, borderColor: Colors.border, borderRadius: 10, padding: 14, alignItems: "center", }} > Edit Delete Incident ); }