@visns-studio/visns-components 5.15.7 → 5.15.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,280 @@
1
+ import React from 'react';
2
+ import {
3
+ Document,
4
+ Page,
5
+ View,
6
+ Text,
7
+ Image,
8
+ StyleSheet,
9
+ } from '@react-pdf/renderer';
10
+ import { getCameraById } from '../data/verkadaCameras';
11
+
12
+ // Simple styles using only built-in fonts and basic styling
13
+ const styles = StyleSheet.create({
14
+ page: {
15
+ fontFamily: 'Helvetica',
16
+ fontSize: 11,
17
+ padding: 30,
18
+ backgroundColor: '#ffffff',
19
+ },
20
+ landscapePage: {
21
+ fontFamily: 'Helvetica',
22
+ fontSize: 11,
23
+ padding: 20,
24
+ backgroundColor: '#ffffff',
25
+ },
26
+ header: {
27
+ backgroundColor: '#2563eb',
28
+ color: '#ffffff',
29
+ padding: 20,
30
+ marginBottom: 20,
31
+ textAlign: 'center',
32
+ },
33
+ title: {
34
+ fontSize: 20,
35
+ marginBottom: 10,
36
+ },
37
+ subtitle: {
38
+ fontSize: 12,
39
+ marginBottom: 10,
40
+ },
41
+ dateInfo: {
42
+ fontSize: 10,
43
+ marginTop: 10,
44
+ },
45
+ mapContainer: {
46
+ flex: 1,
47
+ textAlign: 'center',
48
+ justifyContent: 'center',
49
+ backgroundColor: '#f9fafb',
50
+ padding: 20,
51
+ marginTop: 20,
52
+ },
53
+ mapImage: {
54
+ maxWidth: '100%',
55
+ maxHeight: '70%',
56
+ },
57
+ mapPlaceholder: {
58
+ fontSize: 14,
59
+ color: '#6b7280',
60
+ textAlign: 'center',
61
+ padding: 40,
62
+ },
63
+ detailsTitle: {
64
+ fontSize: 18,
65
+ marginBottom: 20,
66
+ textAlign: 'center',
67
+ color: '#1f2937',
68
+ },
69
+ cameraCard: {
70
+ marginBottom: 15,
71
+ border: '1 solid #e5e7eb',
72
+ backgroundColor: '#ffffff',
73
+ },
74
+ cameraHeader: {
75
+ backgroundColor: '#3b82f6',
76
+ color: '#ffffff',
77
+ padding: 10,
78
+ flexDirection: 'row',
79
+ },
80
+ cameraNumber: {
81
+ width: 25,
82
+ height: 25,
83
+ backgroundColor: '#ffffff',
84
+ color: '#3b82f6',
85
+ textAlign: 'center',
86
+ marginRight: 10,
87
+ fontSize: 12,
88
+ },
89
+ cameraTitle: {
90
+ flex: 1,
91
+ },
92
+ cameraTitleText: {
93
+ fontSize: 14,
94
+ marginBottom: 2,
95
+ },
96
+ cameraModel: {
97
+ fontSize: 10,
98
+ opacity: 0.9,
99
+ },
100
+ cameraContent: {
101
+ padding: 12,
102
+ },
103
+ specRow: {
104
+ flexDirection: 'row',
105
+ marginBottom: 5,
106
+ },
107
+ specLabel: {
108
+ width: 80,
109
+ fontSize: 10,
110
+ color: '#6b7280',
111
+ },
112
+ specValue: {
113
+ flex: 1,
114
+ fontSize: 10,
115
+ color: '#1f2937',
116
+ },
117
+ coordinates: {
118
+ marginTop: 10,
119
+ padding: 8,
120
+ backgroundColor: '#f3f4f6',
121
+ fontSize: 9,
122
+ },
123
+ footer: {
124
+ marginTop: 20,
125
+ padding: 15,
126
+ backgroundColor: '#f9fafb',
127
+ fontSize: 9,
128
+ },
129
+ footerTitle: {
130
+ fontSize: 12,
131
+ marginBottom: 10,
132
+ textAlign: 'center',
133
+ },
134
+ noteText: {
135
+ marginBottom: 5,
136
+ lineHeight: 1.4,
137
+ },
138
+ disclaimer: {
139
+ textAlign: 'center',
140
+ marginTop: 15,
141
+ fontSize: 8,
142
+ color: '#6b7280',
143
+ },
144
+ });
145
+
146
+ // Simple Camera Card Component
147
+ const SimpleCameraCard = ({ camera, number, mode }) => {
148
+ const verkadaCamera = camera.verkadaModel
149
+ ? getCameraById(camera.verkadaModel)
150
+ : null;
151
+
152
+ return (
153
+ <View style={styles.cameraCard}>
154
+ <View style={styles.cameraHeader}>
155
+ <View style={styles.cameraNumber}>
156
+ <Text>{number}</Text>
157
+ </View>
158
+ <View style={styles.cameraTitle}>
159
+ <Text style={styles.cameraTitleText}>Camera {number}</Text>
160
+ <Text style={styles.cameraModel}>
161
+ {verkadaCamera ? verkadaCamera.name : 'Model Not Selected'}
162
+ </Text>
163
+ </View>
164
+ </View>
165
+
166
+ <View style={styles.cameraContent}>
167
+ {verkadaCamera ? (
168
+ <View>
169
+ <View style={styles.specRow}>
170
+ <Text style={styles.specLabel}>Resolution:</Text>
171
+ <Text style={styles.specValue}>{verkadaCamera.resolution}</Text>
172
+ </View>
173
+ <View style={styles.specRow}>
174
+ <Text style={styles.specLabel}>FOV:</Text>
175
+ <Text style={styles.specValue}>{verkadaCamera.fov}°</Text>
176
+ </View>
177
+ <View style={styles.specRow}>
178
+ <Text style={styles.specLabel}>Environment:</Text>
179
+ <Text style={styles.specValue}>{verkadaCamera.environment}</Text>
180
+ </View>
181
+ <View style={styles.specRow}>
182
+ <Text style={styles.specLabel}>IR Range:</Text>
183
+ <Text style={styles.specValue}>{verkadaCamera.irRange}m</Text>
184
+ </View>
185
+ <View style={styles.specRow}>
186
+ <Text style={styles.specLabel}>Direction:</Text>
187
+ <Text style={styles.specValue}>
188
+ {camera.direction ? `${camera.direction}° from North` : 'Not set'}
189
+ </Text>
190
+ </View>
191
+ </View>
192
+ ) : (
193
+ <Text style={{ color: '#dc2626', fontSize: 10 }}>
194
+ No camera model selected - Please configure before installation
195
+ </Text>
196
+ )}
197
+
198
+ <View style={styles.coordinates}>
199
+ <Text>
200
+ Coordinates: {mode === 'map'
201
+ ? `${camera.lat?.toFixed(6)}, ${camera.lng?.toFixed(6)}`
202
+ : `X: ${Math.round(camera.x)}, Y: ${Math.round(camera.y)}`}
203
+ </Text>
204
+ </View>
205
+ </View>
206
+ </View>
207
+ );
208
+ };
209
+
210
+ // Main Simple PDF Document Component
211
+ const SimpleCameraReportPDF = ({ cameras, mapImageData, mode, customColors }) => {
212
+ const currentDate = new Date();
213
+ const reportId = Date.now().toString(36).toUpperCase();
214
+
215
+ return (
216
+ <Document
217
+ title="Security Camera Installation Report"
218
+ author="VISNS Studio"
219
+ subject="Camera Installation Layout"
220
+ >
221
+ {/* Page 1: Site Map */}
222
+ <Page size="A4" orientation="landscape" style={styles.landscapePage}>
223
+ <View style={styles.header}>
224
+ <Text style={styles.title}>Security Camera Installation Report</Text>
225
+ <Text style={styles.subtitle}>Site Layout & Camera Placement Plan</Text>
226
+ <Text style={styles.dateInfo}>
227
+ Generated: {currentDate.toLocaleDateString()} | Report ID: {reportId}
228
+ </Text>
229
+ </View>
230
+
231
+ <View style={styles.mapContainer}>
232
+ {mapImageData ? (
233
+ <Image src={mapImageData} style={styles.mapImage} />
234
+ ) : (
235
+ <Text style={styles.mapPlaceholder}>
236
+ Site map will be displayed here{'\n'}
237
+ Please upload an image to include the site layout
238
+ </Text>
239
+ )}
240
+ </View>
241
+ </Page>
242
+
243
+ {/* Page 2: Camera Details */}
244
+ <Page size="A4" style={styles.page}>
245
+ <Text style={styles.detailsTitle}>Camera Specifications & Details</Text>
246
+
247
+ {cameras.map((camera, index) => (
248
+ <SimpleCameraCard
249
+ key={camera.id}
250
+ camera={camera}
251
+ number={index + 1}
252
+ mode={mode}
253
+ />
254
+ ))}
255
+
256
+ <View style={styles.footer}>
257
+ <Text style={styles.footerTitle}>Installation Notes</Text>
258
+ <Text style={styles.noteText}>
259
+ • Direction measurements are clockwise from North (0° = North, 90° = East, 180° = South, 270° = West)
260
+ </Text>
261
+ <Text style={styles.noteText}>
262
+ • Field of View angles represent horizontal viewing angle
263
+ </Text>
264
+ <Text style={styles.noteText}>
265
+ • Coordinates are {mode === 'map' ? 'geographic (Lat, Lng)' : 'pixel coordinates (X, Y)'}
266
+ </Text>
267
+ <Text style={styles.noteText}>
268
+ • Verify layout on-site - placement may need adjustment based on physical constraints
269
+ </Text>
270
+
271
+ <Text style={styles.disclaimer}>
272
+ Report ID: {reportId} | Generated automatically - Review by qualified professionals recommended
273
+ </Text>
274
+ </View>
275
+ </Page>
276
+ </Document>
277
+ );
278
+ };
279
+
280
+ export default SimpleCameraReportPDF;