samre-cli 1.0.0 → 1.0.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samre-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "CLI officiel d'injection automatique du SDK Samré dans les applications mobiles (Flutter, React Native)",
5
5
  "main": "bin/samre.js",
6
6
  "bin": {
@@ -1,4 +1,4 @@
1
- // Modèle complet pour lib/samre_sdk.dart
1
+ // Modèle complet pour lib/samre_sdk.dart (Version 100% autonome sans dépendance au Navigator)
2
2
 
3
3
  export function generateFlutterSdkCode({ apiUrl, apiKey, appId, appName, dureeJours }) {
4
4
  return `// =================================================================
@@ -33,6 +33,7 @@ class SamreOverlay extends StatefulWidget {
33
33
  class _SamreOverlayState extends State<SamreOverlay> {
34
34
  int _secondsRemaining = SamreConfig.requiredDurationSeconds;
35
35
  bool _canSubmit = false;
36
+ bool _showValidationDialog = false;
36
37
  Timer? _timer;
37
38
 
38
39
  @override
@@ -62,69 +63,91 @@ class _SamreOverlayState extends State<SamreOverlay> {
62
63
  super.dispose();
63
64
  }
64
65
 
65
- void _openValidationDialog() {
66
- showDialog(
67
- context: context,
68
- barrierDismissible: false,
69
- builder: (ctx) => const SamreValidationDialog(),
70
- );
66
+ void _openDialog() {
67
+ setState(() => _showValidationDialog = true);
68
+ }
69
+
70
+ void _closeDialog() {
71
+ setState(() => _showValidationDialog = false);
71
72
  }
72
73
 
73
74
  @override
74
75
  Widget build(BuildContext context) {
75
- return Stack(
76
- children: [
77
- widget.child,
78
- Positioned(
79
- bottom: 24,
80
- right: 20,
81
- child: Material(
82
- elevation: 8,
83
- borderRadius: BorderRadius.circular(24),
84
- color: _canSubmit ? const Color(0xFF2563EB) : Colors.black.withOpacity(0.75),
85
- child: InkWell(
76
+ return Directionality(
77
+ textDirection: TextDirection.ltr,
78
+ child: Stack(
79
+ children: [
80
+ widget.child,
81
+
82
+ // ── Bouton Flottant en Bas à Droite ──────────────────────────────
83
+ Positioned(
84
+ bottom: 24,
85
+ right: 20,
86
+ child: Material(
87
+ elevation: 8,
86
88
  borderRadius: BorderRadius.circular(24),
87
- onTap: _canSubmit ? _openValidationDialog : null,
88
- child: Padding(
89
- padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
90
- child: Row(
91
- mainAxisSize: MainAxisSize.min,
92
- children: [
93
- Icon(
94
- _canSubmit ? Icons.verified_user : Icons.timer_outlined,
95
- color: Colors.white,
96
- size: 18,
97
- ),
98
- const SizedBox(width: 8),
99
- Text(
100
- _canSubmit ? 'Valider Journée' : 'Test en cours (\${_secondsRemaining}s)',
101
- style: const TextStyle(
89
+ color: _canSubmit ? const Color(0xFF2563EB) : Colors.black.withOpacity(0.75),
90
+ child: InkWell(
91
+ borderRadius: BorderRadius.circular(24),
92
+ onTap: _canSubmit ? _openDialog : null,
93
+ child: Padding(
94
+ padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
95
+ child: Row(
96
+ mainAxisSize: MainAxisSize.min,
97
+ children: [
98
+ Icon(
99
+ _canSubmit ? Icons.verified_user : Icons.timer_outlined,
102
100
  color: Colors.white,
103
- fontWeight: FontWeight.bold,
104
- fontSize: 12,
105
- decoration: TextDecoration.none,
101
+ size: 18,
102
+ ),
103
+ const SizedBox(width: 8),
104
+ Text(
105
+ _canSubmit ? 'Valider Journée' : 'Test en cours (\${_secondsRemaining}s)',
106
+ style: const TextStyle(
107
+ color: Colors.white,
108
+ fontWeight: FontWeight.bold,
109
+ fontSize: 12,
110
+ decoration: TextDecoration.none,
111
+ ),
106
112
  ),
107
- ),
108
- ],
113
+ ],
114
+ ),
109
115
  ),
110
116
  ),
111
117
  ),
112
118
  ),
113
- ),
114
- ],
119
+
120
+ // ── Fenêtre Modale de Validation (Indépendante du Navigator) ─────
121
+ if (_showValidationDialog)
122
+ Positioned.fill(
123
+ child: Container(
124
+ color: Colors.black.withOpacity(0.75),
125
+ alignment: Alignment.center,
126
+ padding: const EdgeInsets.symmetric(horizontal: 20),
127
+ child: Material(
128
+ color: Colors.transparent,
129
+ child: SamreValidationCard(
130
+ onClose: _closeDialog,
131
+ ),
132
+ ),
133
+ ),
134
+ ),
135
+ ],
136
+ ),
115
137
  );
116
138
  }
117
139
  }
118
140
 
119
- /// Boîte de dialogue de validation du code quotidien par le panéliste
120
- class SamreValidationDialog extends StatefulWidget {
121
- const SamreValidationDialog({Key? key}) : super(key: key);
141
+ /// Carte de dialogue de validation du code quotidien
142
+ class SamreValidationCard extends StatefulWidget {
143
+ final VoidCallback onClose;
144
+ const SamreValidationCard({Key? key, required this.onClose}) : super(key: key);
122
145
 
123
146
  @override
124
- State<SamreValidationDialog> createState() => _SamreValidationDialogState();
147
+ State<SamreValidationCard> createState() => _SamreValidationCardState();
125
148
  }
126
149
 
127
- class _SamreValidationDialogState extends State<SamreValidationDialog> {
150
+ class _SamreValidationCardState extends State<SamreValidationCard> {
128
151
  final _panelisteCtrl = TextEditingController();
129
152
  final _codeCtrl = TextEditingController();
130
153
  bool _loading = false;
@@ -163,6 +186,7 @@ class _SamreValidationDialogState extends State<SamreValidationDialog> {
163
186
  'Content-Type': 'application/json',
164
187
  'Accept': 'application/json',
165
188
  'X-App-Key': SamreConfig.apiKey,
189
+ 'ngrok-skip-browser-warning': '1',
166
190
  },
167
191
  body: jsonEncode({
168
192
  'apiKey': SamreConfig.apiKey,
@@ -199,103 +223,136 @@ class _SamreValidationDialogState extends State<SamreValidationDialog> {
199
223
 
200
224
  @override
201
225
  Widget build(BuildContext context) {
202
- return AlertDialog(
203
- backgroundColor: const Color(0xFF0F172A),
204
- shape: RoundedRectangleBorder(
205
- borderRadius: BorderRadius.circular(20),
206
- side: const BorderSide(color: Color(0xFF334155)),
207
- ),
208
- title: Row(
209
- children: [
210
- Container(
211
- padding: const EdgeInsets.all(8),
212
- decoration: BoxDecoration(
213
- color: const Color(0xFF2563EB).withOpacity(0.2),
214
- borderRadius: BorderRadius.circular(10),
215
- ),
216
- child: const Icon(Icons.verified, color: Color(0xFF60A5FA), size: 22),
217
- ),
218
- const SizedBox(width: 12),
219
- const Expanded(
220
- child: Text(
221
- 'Validation Samré',
222
- style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
223
- ),
226
+ return Container(
227
+ constraints: const BoxConstraints(maxWidth: 420),
228
+ decoration: BoxDecoration(
229
+ color: const Color(0xFF0F172A),
230
+ borderRadius: BorderRadius.circular(24),
231
+ border: Border.all(color: const Color(0xFF334155), width: 1.5),
232
+ boxShadow: [
233
+ BoxShadow(
234
+ color: Colors.black.withOpacity(0.5),
235
+ blurRadius: 25,
236
+ spreadRadius: 5,
224
237
  ),
225
238
  ],
226
239
  ),
227
- content: SingleChildScrollView(
228
- child: Column(
229
- mainAxisSize: MainAxisSize.min,
230
- crossAxisAlignment: CrossAxisAlignment.stretch,
231
- children: [
232
- const Text(
233
- 'Saisissez vos identifiants fournis par la plateforme Samré pour enregistrer votre journée.',
234
- style: TextStyle(color: Color(0xFF94A3B8), fontSize: 13),
235
- ),
236
- const SizedBox(height: 16),
237
- TextField(
238
- controller: _panelisteCtrl,
239
- style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
240
- decoration: InputDecoration(
241
- labelText: 'Identifiant Panéliste',
242
- labelStyle: const TextStyle(color: Color(0xFF94A3B8)),
243
- hintText: 'Ex: TST-7A8B9C',
244
- hintStyle: const TextStyle(color: Color(0xFF475569)),
245
- filled: true,
246
- fillColor: const Color(0xFF1E293B),
247
- border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
248
- ),
249
- ),
250
- const SizedBox(height: 12),
251
- TextField(
252
- controller: _codeCtrl,
253
- textCapitalization: TextCapitalization.characters,
254
- style: const TextStyle(color: Colors.white, letterSpacing: 2, fontWeight: FontWeight.bold),
255
- decoration: InputDecoration(
256
- labelText: 'Code Unique du Jour',
257
- labelStyle: const TextStyle(color: Color(0xFF94A3B8)),
258
- hintText: 'Ex: 7K9P-4MX2',
259
- hintStyle: const TextStyle(color: Color(0xFF475569), letterSpacing: 0),
260
- filled: true,
261
- fillColor: const Color(0xFF1E293B),
262
- border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
263
- ),
264
- ),
265
- if (_message != null) ...[
266
- const SizedBox(height: 14),
240
+ padding: const EdgeInsets.all(22),
241
+ child: Column(
242
+ mainAxisSize: MainAxisSize.min,
243
+ crossAxisAlignment: CrossAxisAlignment.stretch,
244
+ children: [
245
+ // Titre
246
+ Row(
247
+ children: [
267
248
  Container(
268
- padding: const EdgeInsets.all(12),
249
+ padding: const EdgeInsets.all(8),
269
250
  decoration: BoxDecoration(
270
- color: _success ? const Color(0xFF065F46).withOpacity(0.3) : const Color(0xFF991B1B).withOpacity(0.3),
251
+ color: const Color(0xFF2563EB).withOpacity(0.2),
271
252
  borderRadius: BorderRadius.circular(10),
272
- border: Border.all(color: _success ? const Color(0xFF10B981) : const Color(0xFFEF4444)),
273
253
  ),
254
+ child: const Icon(Icons.verified, color: Color(0xFF60A5FA), size: 22),
255
+ ),
256
+ const SizedBox(width: 12),
257
+ const Expanded(
274
258
  child: Text(
275
- _message!,
276
- style: TextStyle(color: _success ? const Color(0xFF34D399) : const Color(0xFFF87171), fontSize: 12, fontWeight: FontWeight.w600),
259
+ 'Validation Samré',
260
+ style: TextStyle(
261
+ color: Colors.white,
262
+ fontSize: 18,
263
+ fontWeight: FontWeight.bold,
264
+ ),
277
265
  ),
278
266
  ),
267
+ IconButton(
268
+ icon: const Icon(Icons.close, color: Color(0xFF94A3B8), size: 20),
269
+ onPressed: widget.onClose,
270
+ ),
279
271
  ],
272
+ ),
273
+ const SizedBox(height: 12),
274
+ const Text(
275
+ 'Saisissez vos identifiants pour enregistrer votre journée de test.',
276
+ style: TextStyle(color: Color(0xFF94A3B8), fontSize: 13),
277
+ ),
278
+ const SizedBox(height: 16),
279
+ TextField(
280
+ controller: _panelisteCtrl,
281
+ style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
282
+ decoration: InputDecoration(
283
+ labelText: 'Identifiant Panéliste',
284
+ labelStyle: const TextStyle(color: Color(0xFF94A3B8)),
285
+ hintText: 'Ex: TST-7A8B9C',
286
+ hintStyle: const TextStyle(color: Color(0xFF475569)),
287
+ filled: true,
288
+ fillColor: const Color(0xFF1E293B),
289
+ border: OutlineInputBorder(
290
+ borderRadius: BorderRadius.circular(12),
291
+ borderSide: const BorderSide(color: Color(0xFF334155)),
292
+ ),
293
+ ),
294
+ ),
295
+ const SizedBox(height: 12),
296
+ TextField(
297
+ controller: _codeCtrl,
298
+ textCapitalization: TextCapitalization.characters,
299
+ style: const TextStyle(color: Colors.white, letterSpacing: 2, fontWeight: FontWeight.bold),
300
+ decoration: InputDecoration(
301
+ labelText: 'Code Unique du Jour',
302
+ labelStyle: const TextStyle(color: Color(0xFF94A3B8)),
303
+ hintText: 'Ex: 7K9P-4MX2',
304
+ hintStyle: const TextStyle(color: Color(0xFF475569), letterSpacing: 0),
305
+ filled: true,
306
+ fillColor: const Color(0xFF1E293B),
307
+ border: OutlineInputBorder(
308
+ borderRadius: BorderRadius.circular(12),
309
+ borderSide: const BorderSide(color: Color(0xFF334155)),
310
+ ),
311
+ ),
312
+ ),
313
+ if (_message != null) ...[
314
+ const SizedBox(height: 14),
315
+ Container(
316
+ padding: const EdgeInsets.all(12),
317
+ decoration: BoxDecoration(
318
+ color: _success ? const Color(0xFF065F46).withOpacity(0.3) : const Color(0xFF991B1B).withOpacity(0.3),
319
+ borderRadius: BorderRadius.circular(10),
320
+ border: Border.all(color: _success ? const Color(0xFF10B981) : const Color(0xFFEF4444)),
321
+ ),
322
+ child: Text(
323
+ _message!,
324
+ style: TextStyle(
325
+ color: _success ? const Color(0xFF34D399) : const Color(0xFFF87171),
326
+ fontSize: 12,
327
+ fontWeight: FontWeight.w600,
328
+ ),
329
+ ),
330
+ ),
280
331
  ],
281
- ),
282
- ),
283
- actions: [
284
- TextButton(
285
- onPressed: () => Navigator.pop(context),
286
- child: const Text('Fermer', style: TextStyle(color: Color(0xFF94A3B8))),
287
- ),
288
- ElevatedButton(
289
- onPressed: _loading ? null : _verify,
290
- style: ElevatedButton.styleFrom(
291
- backgroundColor: const Color(0xFF2563EB),
292
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
332
+ const SizedBox(height: 18),
333
+ Row(
334
+ mainAxisAlignment: MainAxisAlignment.end,
335
+ children: [
336
+ TextButton(
337
+ onPressed: widget.onClose,
338
+ child: const Text('Fermer', style: TextStyle(color: Color(0xFF94A3B8))),
339
+ ),
340
+ const SizedBox(width: 8),
341
+ ElevatedButton(
342
+ onPressed: _loading ? null : _verify,
343
+ style: ElevatedButton.styleFrom(
344
+ backgroundColor: const Color(0xFF2563EB),
345
+ padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
346
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
347
+ ),
348
+ child: _loading
349
+ ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2))
350
+ : const Text('Valider', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
351
+ ),
352
+ ],
293
353
  ),
294
- child: _loading
295
- ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2))
296
- : const Text('Valider', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
297
- ),
298
- ],
354
+ ],
355
+ ),
299
356
  );
300
357
  }
301
358
  }
package/src/utils/api.js CHANGED
@@ -14,7 +14,8 @@ export async function fetchIntegrationInfo(apiUrl, token) {
14
14
  method: 'GET',
15
15
  headers: {
16
16
  'Accept': 'application/json',
17
- 'User-Agent': 'samre-cli/1.0.0'
17
+ 'User-Agent': 'samre-cli/1.0.1',
18
+ 'ngrok-skip-browser-warning': '1'
18
19
  }
19
20
  });
20
21