QRCode.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. 'use client';
  2. import './style.scss';
  3. import { useCallback } from 'react';
  4. import { QRCodeSVG } from 'qrcode.react';
  5. import { Button } from '@/components/ui/button';
  6. import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
  7. import { getDateFilename } from '@/lib/utils/client';
  8. type Props = {
  9. isEnable: boolean;
  10. open: boolean;
  11. onChange: (open: boolean) => void;
  12. }
  13. export default function QRCode({ isEnable, open, onChange }: Props)
  14. {
  15. const handleDownload = useCallback(() => {
  16. const svgElement = document.getElementById('qrCode');
  17. if (!svgElement) {
  18. return;
  19. }
  20. const svgData = new XMLSerializer().serializeToString(svgElement);
  21. const canvas = document.createElement('canvas');
  22. const ctx = canvas.getContext('2d')!;
  23. const img = new Image();
  24. img.onload = () => {
  25. canvas.width = img.width;
  26. canvas.height = img.height;
  27. ctx.drawImage(img, 0, 0);
  28. const pngFile = canvas.toDataURL('image/png');
  29. const link = document.createElement('a');
  30. link.download = getDateFilename('qr');
  31. link.href = pngFile;
  32. link.click();
  33. };
  34. img.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgData)));
  35. }, []);
  36. if (!isEnable) {
  37. return null;
  38. }
  39. return (
  40. <Dialog open={open} onOpenChange={onChange}>
  41. <DialogContent className='sm:max-w-md'>
  42. <DialogHeader>
  43. <DialogTitle>게시글 확인 QR</DialogTitle>
  44. <DialogDescription>
  45. 아래 QR을 스캔하여 게시글을 확인할 수 있습니다.
  46. </DialogDescription>
  47. </DialogHeader>
  48. <div className='flex items-center justify-center space-x-2'>
  49. <QRCodeSVG id='qrCode' value={window.location.href} />
  50. </div>
  51. <DialogFooter className='sm:justify-center'>
  52. <DialogClose asChild>
  53. <Button type='button' variant='outline' className='hover:bg-blue-500 hover:text-white sm:w-24' onClick={handleDownload}>
  54. 저장
  55. </Button>
  56. </DialogClose>
  57. </DialogFooter>
  58. </DialogContent>
  59. </Dialog>
  60. );
  61. }