import React from 'react'; import { View, StyleSheet, ScrollView, RefreshControl } from 'react-native'; import { Card, Text, Divider } from 'react-native-paper'; import { useQuery } from '@tanstack/react-query'; import { useRoute } from '@react-navigation/native'; import type { NativeStackScreenProps } from '@react-navigation/native-stack'; import { StatusChip } from '../../components/StatusChip'; import { PriorityChip } from '../../components/PriorityChip'; import { LineItemRow } from '../../components/LineItemRow'; import { EmptyState } from '../../components/EmptyState'; import { proposalsApi } from '../../lib/api/proposals'; import { lineItemsApi } from '../../lib/api/lineItems'; import { QUERY_KEYS } from '../../constants/queryKeys'; import type { ProposalsStackParamList } from '../../navigation/types'; type RouteProps = NativeStackScreenProps< ProposalsStackParamList, 'ProposalDetail' >['route']; export function ProposalDetailScreen() { const route = useRoute(); const { proposalId } = route.params; const proposalQuery = useQuery({ queryKey: [QUERY_KEYS.proposal, proposalId], queryFn: () => proposalsApi.getById(proposalId), }); const lineItemsQuery = useQuery({ queryKey: [QUERY_KEYS.proposalLineItems, proposalId], queryFn: () => lineItemsApi.getAll(proposalId), }); const proposal = proposalQuery.data; const lineItems = lineItemsQuery.data ?? []; const refreshing = proposalQuery.isRefetching || lineItemsQuery.isRefetching; const onRefresh = () => { proposalQuery.refetch(); lineItemsQuery.refetch(); }; if (!proposal && proposalQuery.isLoading) { return ( ); } if (!proposal) { return ( ); } const total = lineItems.reduce((sum, li) => sum + li.totalPrice, 0); return ( } > {proposal.proposalNumber} WO# {proposal.workOrderNumber} Customer {proposal.customerName} {proposal.customerAddress} Scope of Work {proposal.refinedScope || proposal.scopeOfWork} {lineItems.length > 0 && ( Line Items ${total.toLocaleString()} {lineItems.map((item, i) => ( ))} )} Timeline {proposal.approvedAt && ( )} {proposal.sentAt && ( )} ); } function TimelineEntry({ label, date, name, }: { label: string; date: string; name?: string | null; }) { return ( {label} {new Date(date).toLocaleString()} {name ? ` by ${name}` : ''} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#FAFAFA', }, card: { marginHorizontal: 16, marginTop: 12, }, headerRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8, }, number: { fontWeight: '700', }, metaRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, metaLabel: { color: '#757575', }, sectionTitle: { fontWeight: '600', marginBottom: 8, }, address: { color: '#757575', marginTop: 4, }, lineItemsHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, totalBadge: { color: '#2E7D32', fontWeight: '700', }, timelineEntry: { flexDirection: 'row', alignItems: 'flex-start', gap: 12, marginBottom: 12, }, timelineDot: { width: 10, height: 10, borderRadius: 5, backgroundColor: '#1565C0', marginTop: 5, }, timelineLabel: { fontWeight: '600', }, timelineDate: { color: '#757575', }, bottomPadding: { height: 24, }, });