/** * Primitivas de UI compartidas (botones, tarjetas, badges, campos). * Estilo sobrio, pensado para uso en campo (targets grandes, buen contraste). */ import React, { ReactNode } from 'react'; import { ActivityIndicator, StyleProp, StyleSheet, Text, TextInput, TextInputProps, TouchableOpacity, View, ViewStyle, } from 'react-native'; export const COLORS = { primary: '#1f6f43', warn: '#8a6d00', danger: '#b00020', muted: '#666', border: '#ddd', bg: '#f4f4f4', }; export const ISSUE_STATUS_COLOR: Record = { open: COLORS.danger, in_review: COLORS.warn, resolved: COLORS.primary, closed: COLORS.muted, }; export const ISSUE_PRIORITY_COLOR: Record = { low: COLORS.muted, medium: COLORS.primary, high: COLORS.warn, critical: COLORS.danger, }; export function Badge({ label, color }: { label: string; color: string }) { return ( {label} ); } export function PrimaryButton({ title, onPress, disabled, loading, variant = 'primary', }: { title: string; onPress: () => void; disabled?: boolean; loading?: boolean; variant?: 'primary' | 'danger' | 'ghost'; }) { const bg = variant === 'danger' ? COLORS.danger : variant === 'ghost' ? 'transparent' : COLORS.primary; const fg = variant === 'ghost' ? COLORS.primary : '#fff'; return ( {loading ? ( ) : ( {title} )} ); } export function Card({ children, style, }: { children: ReactNode; style?: StyleProp; }) { return {children}; } export function SectionTitle({ children }: { children: ReactNode }) { return {children}; } export function EmptyState({ text }: { text: string }) { return {text}; } export function Field({ label, ...props }: TextInputProps & { label: string }) { return ( {label} ); } /** Selector simple de opciones (chips). */ export function ChipSelect({ label, value, options, onChange, }: { label: string; value: T | undefined; options: readonly T[]; onChange: (v: T) => void; }) { return ( {label} {options.map((opt) => { const active = opt === value; return ( onChange(opt)} > {opt} ); })} ); } const styles = StyleSheet.create({ badge: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 10, alignSelf: 'flex-start' }, badgeText: { color: '#fff', fontSize: 11, fontWeight: '700' }, button: { borderRadius: 8, paddingVertical: 13, paddingHorizontal: 16, alignItems: 'center', justifyContent: 'center', }, buttonGhost: { borderWidth: 1, borderColor: COLORS.primary }, buttonDisabled: { opacity: 0.5 }, buttonText: { fontSize: 15, fontWeight: '700' }, card: { backgroundColor: COLORS.bg, borderRadius: 10, padding: 12, }, sectionTitle: { fontSize: 16, fontWeight: '700', marginTop: 8, marginBottom: 4 }, empty: { color: '#888', textAlign: 'center', marginTop: 24 }, field: { marginBottom: 12 }, fieldLabel: { fontSize: 13, color: COLORS.muted, marginBottom: 4, fontWeight: '600' }, input: { borderWidth: 1, borderColor: COLORS.border, borderRadius: 8, paddingHorizontal: 12, paddingVertical: 10, fontSize: 16, backgroundColor: '#fff', }, chips: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 }, chip: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16, borderWidth: 1, borderColor: COLORS.border, backgroundColor: '#fff', }, chipActive: { backgroundColor: COLORS.primary, borderColor: COLORS.primary }, chipText: { fontSize: 13, color: COLORS.muted }, chipTextActive: { color: '#fff', fontWeight: '700' }, });