66 lines
2.0 KiB
TypeScript
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>
|
|
);
|
|
}
|