businessCard/src/components/QRCodeDisplay.tsx

66 lines
2.0 KiB
TypeScript

import { useRef } from 'react';
// @ts-expect-error - qrcode.react doesn't have official TS types
import QRCode from 'qrcode.react';
import { Download } from 'lucide-react';
import { useBusinessCard } from '../store/BusinessCardContext';
import styles from './QRCodeDisplay.module.css';
import type { BusinessCard } from '../store/types';
function generateVCard(businessCard: BusinessCard): string {
const lines = [
'BEGIN:VCARD',
'VERSION:3.0',
`FN:${businessCard.name}`,
`N:${businessCard.name.split(' ').reverse().join(';')}`,
`TITLE:${businessCard.title}`,
`ORG:${businessCard.company}`,
`EMAIL:${businessCard.email}`,
`TEL:${businessCard.phone}`,
businessCard.website ? `URL:${businessCard.website}` : null,
businessCard.image ? `PHOTO;VALUE=URL:${businessCard.image}` : null,
'END:VCARD',
]
.filter(Boolean)
.join('\r\n');
return lines;
}
export function QRCodeDisplay() {
const { businessCard } = useBusinessCard();
const qrRef = useRef<HTMLDivElement>(null);
const vCard = generateVCard(businessCard);
const handleDownload = () => {
const canvas = qrRef.current?.querySelector('canvas');
if (canvas) {
const link = document.createElement('a');
link.href = canvas.toDataURL('image/png');
link.download = `${businessCard.name}-contact.png`;
link.click();
}
};
return (
<div className={styles.container}>
<h2 className={styles.title}>Scan to Add Contact</h2>
<div className={styles.qrWrapper} ref={qrRef}>
<QRCode
value={vCard}
size={256}
level="H"
includeMargin
fgColor="#000000"
bgColor="#ffffff"
/>
</div>
<p className={styles.subtitle}>Scan with any smartphone camera</p>
<button onClick={handleDownload} className={styles.downloadBtn} aria-label="Download QR code">
<Download size={20} />
<span>Download QR Code</span>
</button>
</div>
);
}