Znfeoqm commited on
Commit
c0eaec6
·
verified ·
1 Parent(s): ba5775a

Update src/App.jsx

Browse files
Files changed (1) hide show
  1. src/App.jsx +23 -173
src/App.jsx CHANGED
@@ -28,6 +28,19 @@ const QRGeneratorTab = ({
28
  isInputFocused, setIsInputFocused, currentThemeClasses,
29
  qrStyles, selectedStyleIndex, setSelectedStyleIndex, styleCanvasRefs, drawQrCode
30
  }) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  return (
32
  <div className="flex flex-col lg:flex-row p-4 md:p-6 space-y-6 lg:space-y-0 lg:space-x-6 h-full">
33
  {/* Left Panel: Input and Controls */}
@@ -126,7 +139,7 @@ const QRGeneratorTab = ({
126
 
127
  // --- QRDecoderTab Component (Moved outside App) ---
128
  const QRDecoderTab = ({
129
- decodedContent, setDecodedContent, isSummarizing, setIsSummarizing,
130
  suggestedActions, setSuggestedActions, isSuggestingActions, setIsSuggestingActions,
131
  showSuggestedActions, setShowSuggestedActions, showAlert, decodeQrCode, suggestActions,
132
  currentThemeClasses
@@ -235,7 +248,7 @@ const App = () => {
235
  const [isSuggestingActions, setIsSuggestingActions] = useState(false);
236
  const [showSuggestedActions, setShowSuggestedActions] = useState(false);
237
  const [alertMessage, setAlertMessage] = useState(null);
238
- const [isInputFocused, setIsInputFocused] = useState(false); // State for input focus
239
 
240
  const qrCanvasRef = useRef(null);
241
  const styleCanvasRefs = useRef(Array(12).fill(null));
@@ -278,7 +291,7 @@ const App = () => {
278
  cardBorder: 'border-white/10',
279
  qrPreviewBorder: 'border-blue-500/50',
280
  qrPreviewBg: 'bg-gradient-to-br from-gray-900/30 to-gray-800/30 backdrop-blur-md',
281
- headerGlow: 'from-cyan-400 via-purple-500 to-pink-500 animate-neon-gradient-shift'
282
  },
283
  light: {
284
  bg: 'bg-gradient-to-br from-[#F8F8F8] via-[#E8E8E8] to-[#F8F8F8] animate-gradient-shift-light',
@@ -300,7 +313,7 @@ const App = () => {
300
  cardBorder: 'border-gray-200',
301
  qrPreviewBorder: 'border-blue-400/50',
302
  qrPreviewBg: 'bg-gradient-to-br from-gray-100/60 to-gray-200/60 backdrop-blur-md',
303
- headerGlow: 'from-blue-400 via-green-400 to-yellow-400 animate-neon-gradient-shift'
304
  },
305
  'forest-green': {
306
  bg: 'bg-gradient-to-br from-[#0A2A1A] via-[#1A4A3A] to-[#0A3A2A] animate-gradient-shift',
@@ -322,7 +335,7 @@ const App = () => {
322
  cardBorder: 'border-green-900/15',
323
  qrPreviewBorder: 'border-green-500/50',
324
  qrPreviewBg: 'bg-gradient-to-br from-green-900/30 to-green-800/30 backdrop-blur-md',
325
- headerGlow: 'from-lime-400 via-teal-400 to-emerald-400 animate-neon-gradient-shift'
326
  },
327
  'ocean-blue': {
328
  bg: 'bg-gradient-to-br from-[#001A33] via-[#003366] to-[#002A5A] animate-gradient-shift',
@@ -344,7 +357,7 @@ const App = () => {
344
  cardBorder: 'border-blue-900/15',
345
  qrPreviewBorder: 'border-blue-600/50',
346
  qrPreviewBg: 'bg-gradient-to-br from-blue-950/30 to-blue-900/30 backdrop-blur-md',
347
- headerGlow: 'from-sky-400 via-blue-400 to-indigo-400 animate-neon-gradient-shift'
348
  },
349
  'warm-grey': {
350
  bg: 'bg-gradient-to-br from-[#202020] via-[#404040] to-[#303030] animate-gradient-shift',
@@ -366,7 +379,7 @@ const App = () => {
366
  cardBorder: 'border-gray-700/15',
367
  qrPreviewBorder: 'border-gray-500/50',
368
  qrPreviewBg: 'bg-gradient-to-br from-gray-800/30 to-gray-700/30 backdrop-blur-md',
369
- headerGlow: 'from-yellow-400 via-gray-400 to-orange-400 animate-neon-gradient-shift'
370
  },
371
  'deep-purple': {
372
  bg: 'bg-gradient-to-br from-[#100830] via-[#201040] to-[#180C38] animate-gradient-shift',
@@ -388,7 +401,7 @@ const App = () => {
388
  cardBorder: 'border-purple-900/15',
389
  qrPreviewBorder: 'border-purple-600/50',
390
  qrPreviewBg: 'bg-gradient-to-br from-purple-950/30 to-purple-900/30 backdrop-blur-md',
391
- headerGlow: 'from-fuchsia-400 via-purple-400 to-pink-400 animate-neon-gradient-shift'
392
  },
393
  'sunrise-orange': {
394
  bg: 'bg-gradient-to-br from-[#A0300A] via-[#D0501A] to-[#B84012] animate-gradient-shift',
@@ -410,7 +423,7 @@ const App = () => {
410
  cardBorder: 'border-orange-800/15',
411
  qrPreviewBorder: 'border-orange-600/50',
412
  qrPreviewBg: 'bg-gradient-to-br from-orange-900/30 to-orange-800/30 backdrop-blur-md',
413
- headerGlow: 'from-yellow-400 via-orange-400 to-red-400 animate-neon-gradient-shift'
414
  },
415
  };
416
 
@@ -454,172 +467,10 @@ const App = () => {
454
  }
455
  }, []);
456
 
457
- // Effect to generate QR code on the main canvas (Generator Tab)
458
- useEffect(() => {
459
- drawQrCode(qrCanvasRef.current, content, qrColor, errorLevel);
460
- }, [content, qrColor, errorLevel, drawQrCode]);
461
-
462
- // Effect to generate QR codes for style previews (Style Selection Panel)
463
- useEffect(() => {
464
- qrStyles.forEach((style, index) => {
465
- const canvas = styleCanvasRefs.current[index];
466
- drawQrCode(canvas, "Sample", style.fg, 'H', 80);
467
- });
468
- }, [qrStyles, drawQrCode]);
469
-
470
- // Function to download the generated QR code (remains in App, passed to generator)
471
- const downloadQrCode = () => {
472
- if (content.trim() === '') {
473
- showAlert('Please enter content to generate QR code.');
474
- return;
475
- }
476
- const canvas = qrCanvasRef.current;
477
- if (canvas) {
478
- const pngUrl = canvas.toDataURL("image/png");
479
- const downloadLink = document.createElement('a');
480
- downloadLink.href = pngUrl;
481
- downloadLink.download = 'qrcode.png';
482
- document.body.appendChild(downloadLink);
483
- downloadLink.click();
484
- document.body.removeChild(downloadLink);
485
- }
486
- };
487
-
488
- // Function to decode QR code from an uploaded image (remains in App, passed to decoder)
489
- const decodeQrCode = (event) => {
490
- const file = event.target.files[0];
491
- if (!file) return;
492
-
493
- const reader = new FileReader();
494
- reader.onload = (e) => {
495
- const img = new Image();
496
- img.onload = () => {
497
- const canvas = document.createElement('canvas');
498
- const context = canvas.getContext('2d');
499
- canvas.width = img.width;
500
- canvas.height = img.height;
501
- context.drawImage(img, 0, 0, img.width, img.height);
502
-
503
- const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
504
-
505
- if (jsQR) {
506
- let code = jsQR(imageData.data, imageData.width, imageData.height);
507
-
508
- if (!code) {
509
- for (let i = 0; i < imageData.data.length; i += 4) {
510
- imageData.data[i] = 255 - imageData.data[i];
511
- imageData.data[i + 1] = 255 - imageData.data[i + 1];
512
- imageData.data[i + 2] = 255 - imageData.data[i + 2];
513
- }
514
- code = jsQR(imageData.data, imageData.width, imageData.height);
515
- }
516
-
517
- if (code) {
518
- setDecodedContent(code.data);
519
- setSuggestedActions('');
520
- setShowSuggestedActions(false);
521
- } else {
522
- setDecodedContent('No QR code detected.');
523
- setSuggestedActions('');
524
- setShowSuggestedActions(false);
525
- }
526
- } else {
527
- showAlert('QR decoder library (jsQR) not loaded. Please try again or check internet connection.');
528
- setSuggestedActions('');
529
- setShowSuggestedActions(false);
530
- }
531
- };
532
- img.src = e.target.result;
533
- };
534
- reader.readAsDataURL(file);
535
- };
536
-
537
- // Function to summarize content using Gemini API (remains in App, passed to generator)
538
- const summarizeContent = async () => {
539
- if (!content.trim()) {
540
- showAlert('Please enter content to summarize.');
541
- return;
542
- }
543
-
544
- setIsSummarizing(true);
545
- try {
546
- let chatHistory = [];
547
- const prompt = `Summarize the following text concisely: ${content}`;
548
- chatHistory.push({ role: "user", parts: [{ text: prompt }] });
549
- const payload = { contents: chatHistory };
550
- const apiKey = ""; // Canvas will provide this at runtime
551
- const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`;
552
-
553
- const response = await fetch(apiUrl, {
554
- method: 'POST',
555
- headers: { 'Content-Type': 'application/json' },
556
- body: JSON.stringify(payload)
557
- });
558
-
559
- const result = await response.json();
560
-
561
- if (result.candidates && result.candidates.length > 0 &&
562
- result.candidates[0].content && result.candidates[0].content.parts &&
563
- result.candidates[0].content.parts.length > 0) {
564
- const text = result.candidates[0].content.parts[0].text;
565
- setContent(text);
566
- } else {
567
- showAlert("Failed to summarize content. Please try again.");
568
- }
569
- } catch (error) {
570
- console.error("Error summarizing content:", error);
571
- showAlert("An error occurred while summarizing content.");
572
- } finally {
573
- setIsSummarizing(false);
574
- }
575
- };
576
-
577
- // Function to suggest actions based on decoded content using Gemini API (remains in App, passed to decoder)
578
- const suggestActions = async () => {
579
- if (!decodedContent.trim() || decodedContent === 'No QR code detected.') {
580
- showAlert('Please decode a QR code first to suggest actions.');
581
- return;
582
- }
583
-
584
- setIsSuggestingActions(true);
585
- setSuggestedActions('Thinking...');
586
- setShowSuggestedActions(true);
587
- try {
588
- let chatHistory = [];
589
- const prompt = `Given the following text from a QR code, suggest relevant actions a user might take. Format the suggestions as a bulleted list. Text: "${decodedContent}"`;
590
- chatHistory.push({ role: "user", parts: [{ text: prompt }] });
591
- const payload = { contents: chatHistory };
592
- const apiKey = ""; // Canvas will provide this at runtime
593
- const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`;
594
-
595
- const response = await fetch(apiUrl, {
596
- method: 'POST',
597
- headers: { 'Content-Type': 'application/json' },
598
- body: JSON.stringify(payload)
599
- });
600
-
601
- const result = await response.json();
602
-
603
- if (result.candidates && result.candidates.length > 0 &&
604
- result.candidates[0].content && result.candidates[0].content.parts &&
605
- result.candidates[0].content.parts.length > 0) {
606
- const text = result.candidates[0].content.parts[0].text;
607
- setSuggestedActions(text);
608
- } else {
609
- setSuggestedActions("Could not suggest actions. Please try again.");
610
- }
611
- } catch (error) {
612
- console.error("Error suggesting actions:", error);
613
- setSuggestedActions("An error occurred while suggesting actions.");
614
- } finally {
615
- setIsSuggestingActions(false);
616
- }
617
- };
618
-
619
  return (
620
  <div className={`min-h-screen font-inter antialiased ${currentThemeClasses.bg} ${currentThemeClasses.text} transition-all duration-500 ease-in-out`}>
621
  <div className="container mx-auto p-4 max-w-7xl">
622
- <h1 className={`text-4xl lg:text-5xl font-extrabold text-center mb-8 bg-clip-text text-transparent bg-gradient-to-r ${currentThemeClasses.headerGlow} font-orbitron`}>
623
  QuantumQR Studio
624
  </h1>
625
 
@@ -667,7 +518,6 @@ const App = () => {
667
  {activeTab === 'decoder' && (
668
  <QRDecoderTab
669
  decodedContent={decodedContent} setDecodedContent={setDecodedContent}
670
- isSummarizing={isSummarizing} setIsSummarizing={setIsSummarizing} // Not directly used in decoder, but good to pass if needed later
671
  suggestedActions={suggestedActions} setSuggestedActions={setSuggestedActions}
672
  isSuggestingActions={isSuggestingActions} setIsSuggestingActions={setIsSuggestingActions}
673
  showSuggestedActions={showSuggestedActions} setShowSuggestedActions={setShowSuggestedActions}
 
28
  isInputFocused, setIsInputFocused, currentThemeClasses,
29
  qrStyles, selectedStyleIndex, setSelectedStyleIndex, styleCanvasRefs, drawQrCode
30
  }) => {
31
+ // Effect to generate QR code on the main canvas (Generator Tab)
32
+ useEffect(() => {
33
+ drawQrCode(qrCanvasRef.current, content, qrColor, errorLevel);
34
+ }, [content, qrColor, errorLevel, drawQrCode, qrCanvasRef]); // Added qrCanvasRef to dependencies
35
+
36
+ // Effect to generate QR codes for style previews (Style Selection Panel)
37
+ useEffect(() => {
38
+ qrStyles.forEach((style, index) => {
39
+ const canvas = styleCanvasRefs.current[index];
40
+ drawQrCode(canvas, "Sample", style.fg, 'H', 80);
41
+ });
42
+ }, [qrStyles, drawQrCode, styleCanvasRefs]); // Added styleCanvasRefs to dependencies
43
+
44
  return (
45
  <div className="flex flex-col lg:flex-row p-4 md:p-6 space-y-6 lg:space-y-0 lg:space-x-6 h-full">
46
  {/* Left Panel: Input and Controls */}
 
139
 
140
  // --- QRDecoderTab Component (Moved outside App) ---
141
  const QRDecoderTab = ({
142
+ decodedContent, setDecodedContent,
143
  suggestedActions, setSuggestedActions, isSuggestingActions, setIsSuggestingActions,
144
  showSuggestedActions, setShowSuggestedActions, showAlert, decodeQrCode, suggestActions,
145
  currentThemeClasses
 
248
  const [isSuggestingActions, setIsSuggestingActions] = useState(false);
249
  const [showSuggestedActions, setShowSuggestedActions] = useState(false);
250
  const [alertMessage, setAlertMessage] = useState(null);
251
+ const [isInputFocused, setIsInputFocused] = useState(false);
252
 
253
  const qrCanvasRef = useRef(null);
254
  const styleCanvasRefs = useRef(Array(12).fill(null));
 
291
  cardBorder: 'border-white/10',
292
  qrPreviewBorder: 'border-blue-500/50',
293
  qrPreviewBg: 'bg-gradient-to-br from-gray-900/30 to-gray-800/30 backdrop-blur-md',
294
+ headerGlow: 'animate-quantum-flux' // Using new quantum-flux animation
295
  },
296
  light: {
297
  bg: 'bg-gradient-to-br from-[#F8F8F8] via-[#E8E8E8] to-[#F8F8F8] animate-gradient-shift-light',
 
313
  cardBorder: 'border-gray-200',
314
  qrPreviewBorder: 'border-blue-400/50',
315
  qrPreviewBg: 'bg-gradient-to-br from-gray-100/60 to-gray-200/60 backdrop-blur-md',
316
+ headerGlow: 'animate-quantum-flux-light' // Using new quantum-flux-light animation
317
  },
318
  'forest-green': {
319
  bg: 'bg-gradient-to-br from-[#0A2A1A] via-[#1A4A3A] to-[#0A3A2A] animate-gradient-shift',
 
335
  cardBorder: 'border-green-900/15',
336
  qrPreviewBorder: 'border-green-500/50',
337
  qrPreviewBg: 'bg-gradient-to-br from-green-900/30 to-green-800/30 backdrop-blur-md',
338
+ headerGlow: 'animate-quantum-flux'
339
  },
340
  'ocean-blue': {
341
  bg: 'bg-gradient-to-br from-[#001A33] via-[#003366] to-[#002A5A] animate-gradient-shift',
 
357
  cardBorder: 'border-blue-900/15',
358
  qrPreviewBorder: 'border-blue-600/50',
359
  qrPreviewBg: 'bg-gradient-to-br from-blue-950/30 to-blue-900/30 backdrop-blur-md',
360
+ headerGlow: 'animate-quantum-flux'
361
  },
362
  'warm-grey': {
363
  bg: 'bg-gradient-to-br from-[#202020] via-[#404040] to-[#303030] animate-gradient-shift',
 
379
  cardBorder: 'border-gray-700/15',
380
  qrPreviewBorder: 'border-gray-500/50',
381
  qrPreviewBg: 'bg-gradient-to-br from-gray-800/30 to-gray-700/30 backdrop-blur-md',
382
+ headerGlow: 'animate-quantum-flux'
383
  },
384
  'deep-purple': {
385
  bg: 'bg-gradient-to-br from-[#100830] via-[#201040] to-[#180C38] animate-gradient-shift',
 
401
  cardBorder: 'border-purple-900/15',
402
  qrPreviewBorder: 'border-purple-600/50',
403
  qrPreviewBg: 'bg-gradient-to-br from-purple-950/30 to-purple-900/30 backdrop-blur-md',
404
+ headerGlow: 'animate-quantum-flux'
405
  },
406
  'sunrise-orange': {
407
  bg: 'bg-gradient-to-br from-[#A0300A] via-[#D0501A] to-[#B84012] animate-gradient-shift',
 
423
  cardBorder: 'border-orange-800/15',
424
  qrPreviewBorder: 'border-orange-600/50',
425
  qrPreviewBg: 'bg-gradient-to-br from-orange-900/30 to-orange-800/30 backdrop-blur-md',
426
+ headerGlow: 'animate-quantum-flux'
427
  },
428
  };
429
 
 
467
  }
468
  }, []);
469
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  return (
471
  <div className={`min-h-screen font-inter antialiased ${currentThemeClasses.bg} ${currentThemeClasses.text} transition-all duration-500 ease-in-out`}>
472
  <div className="container mx-auto p-4 max-w-7xl">
473
+ <h1 className={`text-4xl lg:text-5xl font-extrabold text-center mb-8 bg-clip-text text-transparent ${currentThemeClasses.headerGlow} font-orbitron`}>
474
  QuantumQR Studio
475
  </h1>
476
 
 
518
  {activeTab === 'decoder' && (
519
  <QRDecoderTab
520
  decodedContent={decodedContent} setDecodedContent={setDecodedContent}
 
521
  suggestedActions={suggestedActions} setSuggestedActions={setSuggestedActions}
522
  isSuggestingActions={isSuggestingActions} setIsSuggestingActions={setIsSuggestingActions}
523
  showSuggestedActions={showSuggestedActions} setShowSuggestedActions={setShowSuggestedActions}