forked from ZyntariHQ/Invoisio
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSyncStatusBanner.tsx
More file actions
118 lines (111 loc) · 2.97 KB
/
Copy pathSyncStatusBanner.tsx
File metadata and controls
118 lines (111 loc) · 2.97 KB
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
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import { useConnectivityContext } from './ConnectivityProvider';
/**
* SyncStatusBanner provides user-facing feedback about sync operations
* Shows current sync status, progress, and any errors
*/
export function SyncStatusBanner() {
const { syncStatus, triggerSync } = useConnectivityContext();
if (!syncStatus.isSyncing && syncStatus.queue.length === 0) {
return null;
}
const currentOperation = syncStatus.currentOperation;
const hasErrors = syncStatus.queue.some(op => op.status === 'failed');
return (
<View style={[
styles.container,
hasErrors ? styles.errorContainer : styles.normalContainer
]}>
<View style={styles.content}>
{currentOperation ? (
<>
<Text style={styles.statusText}>
{getOperationLabel(currentOperation.type)}
</Text>
{syncStatus.overallProgress > 0 && (
<Text style={styles.progressText}>
{syncStatus.overallProgress}%
</Text>
)}
</>
) : hasErrors ? (
<Text style={styles.statusText}>
Some sync operations failed
</Text>
) : (
<Text style={styles.statusText}>
Preparing sync...
</Text>
)}
</View>
<TouchableOpacity
style={styles.retryButton}
onPress={() => triggerSync()}
>
<Text style={styles.retryButtonText}>
{hasErrors ? 'Retry' : 'Sync'}
</Text>
</TouchableOpacity>
</View>
);
}
function getOperationLabel(type: string): string {
const labels: Record<string, string> = {
drafts: 'Syncing drafts...',
invoices: 'Updating invoices...',
notifications: 'Checking notifications...',
offline_queue: 'Processing queued requests...',
auth_retry: 'Verifying authentication...',
};
return labels[type] || 'Syncing...';
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 12,
marginHorizontal: 16,
marginTop: 8,
borderRadius: 8,
},
normalContainer: {
backgroundColor: '#1a1d2d',
borderWidth: 1,
borderColor: '#2a2d3d',
},
errorContainer: {
backgroundColor: '#2d1a1a',
borderWidth: 1,
borderColor: '#3d2a2a',
},
content: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
},
statusText: {
color: '#ffffff',
fontSize: 14,
fontFamily: 'SpaceGrotesk_400Regular',
},
progressText: {
color: '#6366f1',
fontSize: 14,
fontFamily: 'SpaceGrotesk_600SemiBold',
marginLeft: 8,
},
retryButton: {
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 6,
backgroundColor: '#6366f1',
},
retryButtonText: {
color: '#ffffff',
fontSize: 12,
fontFamily: 'SpaceGrotesk_600SemiBold',
},
});