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 } from "@/lib/db"; import { renderMarkdown } from "@/lib/markdown"; import { pushIncidentToGit } from "@/lib/git"; import type { GitProvider } 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 [provider, template, giteaUrl, giteaToken, giteaOwner, giteaRepo, githubToken, githubOwner, githubRepo, gitlabUrl, gitlabToken, gitlabOwner, gitlabRepo] = await Promise.all([ SecureStore.getItemAsync("git_provider"), SecureStore.getItemAsync("md_template"), SecureStore.getItemAsync("gitea_url"), SecureStore.getItemAsync("gitea_token"), SecureStore.getItemAsync("gitea_owner"), SecureStore.getItemAsync("gitea_repo"), SecureStore.getItemAsync("github_token"), SecureStore.getItemAsync("github_owner"), SecureStore.getItemAsync("github_repo"), SecureStore.getItemAsync("gitlab_url"), SecureStore.getItemAsync("gitlab_token"), SecureStore.getItemAsync("gitlab_owner"), SecureStore.getItemAsync("gitlab_repo"), ]); const p = (provider ?? "gitea") as GitProvider; let url: string | undefined; let token: string | null; let owner: string | null; let repo: string | null; if (p === "gitea") { url = giteaUrl ?? undefined; token = giteaToken; owner = giteaOwner; repo = giteaRepo; } else if (p === "github") { token = githubToken; owner = githubOwner; repo = githubRepo; } else { url = gitlabUrl ?? undefined; token = gitlabToken; owner = gitlabOwner; repo = gitlabRepo; } if (!token || !owner || !repo) { Alert.alert("Git not configured", `Set up ${p.charAt(0).toUpperCase() + p.slice(1)} in Settings first.`); return; } setPushing(true); const result = await pushIncidentToGit( incident, { provider: p, url, token, owner, repo }, template ?? undefined ); setPushing(false); if (result.success) { 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 ); }