fix: tickets freeze (useFocusEffect), comment body render, client status from subscription, activation ticket on install, keyboard avoid payment modal
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { View, Text, ScrollView, TouchableOpacity, ActivityIndicator, Linking, Alert, TextInput, Modal } from 'react-native';
|
||||
import { View, Text, ScrollView, TouchableOpacity, ActivityIndicator, Linking, Alert, TextInput, Modal, KeyboardAvoidingView, Platform } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useLocalSearchParams, router } from 'expo-router';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
@@ -67,6 +67,7 @@ function PayInvoiceModal({ invoice, onClose, onSuccess }: { invoice: any; onClos
|
||||
|
||||
return (
|
||||
<Modal visible animationType="slide" transparent onRequestClose={onClose}>
|
||||
<KeyboardAvoidingView style={{ flex: 1 }} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<TouchableOpacity style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end' }} activeOpacity={1} onPress={onClose}>
|
||||
<TouchableOpacity activeOpacity={1} style={{ backgroundColor: '#FFF', borderTopLeftRadius: 28, borderTopRightRadius: 28, padding: 24 }}>
|
||||
<Text style={{ fontSize: 20, fontWeight: '800', color: '#0F172A', marginBottom: 4 }}>Record Payment</Text>
|
||||
@@ -115,6 +116,7 @@ function PayInvoiceModal({ invoice, onClose, onSuccess }: { invoice: any; onClos
|
||||
</TouchableOpacity>
|
||||
</TouchableOpacity>
|
||||
</TouchableOpacity>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,16 @@ const STATUS_CONFIG: Record<string, { label: string; color: string; bg: string;
|
||||
SUSPENDED: { label: 'Suspended', color: '#92400E', bg: '#FEF3C7', accent: '#D97706' },
|
||||
CANCELLED: { label: 'Cancelled', color: '#991B1B', bg: '#FEE2E2', accent: '#DC2626' },
|
||||
PENDING: { label: 'Pending', color: '#475569', bg: '#F1F5F9', accent: '#94A3B8' },
|
||||
NO_SUB: { label: 'No Sub', color: '#6B7280', bg: '#F1F5F9', accent: '#CBD5E1' },
|
||||
};
|
||||
|
||||
// Client.status is null in API — derive from subscription status instead
|
||||
function getClientStatus(client: any) {
|
||||
const sub = client?.subscriptions?.[0];
|
||||
if (!sub) return 'NO_SUB';
|
||||
return sub.status ?? 'PENDING';
|
||||
}
|
||||
|
||||
export default function ClientsScreen() {
|
||||
const [search, setSearch] = useState('');
|
||||
const { data, isLoading, refetch, isRefetching } = useQuery({
|
||||
@@ -63,7 +71,8 @@ export default function ClientsScreen() {
|
||||
refreshControl={<RefreshControl refreshing={isRefetching} onRefresh={refetch} tintColor="#0891B2" />}
|
||||
contentContainerStyle={{ padding: 16, paddingBottom: 32 }}
|
||||
renderItem={({ item }) => {
|
||||
const st = STATUS_CONFIG[item.status] ?? { label: item.status, color: '#475569', bg: '#F1F5F9', accent: '#94A3B8' };
|
||||
const statusKey = getClientStatus(item);
|
||||
const st = STATUS_CONFIG[statusKey] ?? { label: statusKey, color: '#475569', bg: '#F1F5F9', accent: '#94A3B8' };
|
||||
const plan = item.subscriptions?.[0]?.plan?.name;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
|
||||
Reference in New Issue
Block a user