CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { colors } from '../theme/colors';
import type { GateRunStatus } from '../api/gates';
interface GateStatusBadgeProps {
status: GateRunStatus;
aiRepaired?: boolean;
size?: 'small' | 'medium';
}
function statusLabel(status: GateRunStatus): string {
switch (status) {
case 'passed': return 'Passed';
case 'failed': return 'Failed';
case 'pending': return 'Pending';
case 'running': return 'Running';
case 'error': return 'Error';
}
}
function statusColor(status: GateRunStatus): string {
switch (status) {
case 'passed': return colors.accent;
case 'failed': return colors.accentRed;
case 'pending': return colors.accentYellow;
case 'running': return colors.accentBlue;
case 'error': return colors.accentRed;
}
}
function statusIcon(status: GateRunStatus): string {
switch (status) {
case 'passed': return '✓';
case 'failed': return '✗';
case 'pending': return '◌';
case 'running': return '◌';
case 'error': return '!';
}
}
export function GateStatusBadge({
status,
aiRepaired = false,
size = 'medium',
}: GateStatusBadgeProps): React.ReactElement {
const badgeColor = statusColor(status);
const isSmall = size === 'small';
return (
<View style={styles.wrapper}>
<View
style={[
styles.badge,
isSmall && styles.badgeSmall,
{ borderColor: badgeColor },
]}
>
<Text style={[styles.icon, isSmall && styles.iconSmall, { color: badgeColor }]}>
{statusIcon(status)}
</Text>
<Text style={[styles.label, isSmall && styles.labelSmall, { color: badgeColor }]}>
{statusLabel(status)}
</Text>
</View>
{aiRepaired && (
<View style={styles.aiBadge}>
<Text style={styles.aiText}>AI Repaired</Text>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
wrapper: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
},
badge: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 10,
paddingVertical: 4,
borderRadius: 20,
borderWidth: 1,
gap: 5,
backgroundColor: colors.bgSecondary,
},
badgeSmall: {
paddingHorizontal: 7,
paddingVertical: 2,
},
icon: {
fontSize: 13,
fontWeight: '700',
},
iconSmall: {
fontSize: 11,
},
label: {
fontSize: 13,
fontWeight: '600',
},
labelSmall: {
fontSize: 11,
},
aiBadge: {
paddingHorizontal: 7,
paddingVertical: 2,
borderRadius: 20,
backgroundColor: colors.bgSecondary,
borderWidth: 1,
borderColor: colors.accentPurple,
},
aiText: {
fontSize: 11,
color: colors.accentPurple,
fontWeight: '500',
},
});
|