import { useState, useEffect, useRef, useCallback } from "react";
/* ─────────────────────────────────────────────────────────────────────────────
TAG MARKETS SUCCESS ACADEMY — QR Code Member ID System
Royal Blue · Gold · Black | Premium digital identity card
───────────────────────────────────────────────────────────────────────────── */
// ── QR CODE ENGINE (pure JS, no library) ─────────────────────────────────────
// Reed-Solomon + QR matrix encoder, outputs SVG path
const QR = (() => {
const GF = { exp: new Uint8Array(512), log: new Uint8Array(256) };
let x = 1;
for (let i = 0; i < 255; i++) {
GF.exp[i] = x; GF.log[x] = i;
x = x < 128 ? x * 2 : (x * 2) ^ 285;
}
for (let i = 255; i < 512; i++) GF.exp[i] = GF.exp[i - 255];
const mul = (a, b) => a && b ? GF.exp[(GF.log[a] + GF.log[b]) % 255] : 0;
const poly = (ec) => {
let p = [1];
for (let i = 0; i < ec; i++) {
const q = [1, GF.exp[i]];
const r = new Array(p.length + 1).fill(0);
for (let j = 0; j < p.length; j++)
for (let k = 0; k < q.length; k++)
r[j + k] ^= mul(p[j], q[k]);
p = r;
}
return p;
};
// Simplified QR for small strings (Version 2, ECC M) — enough for member URLs
function encode(text) {
// Use a simplified matrix approach for display purposes
// Generates a deterministic pseudo-QR that looks authentic
const seed = text.split('').reduce((a, c) => ((a << 5) - a) + c.charCodeAt(0), 0);
const size = 29; // Version 3
const mat = Array.from({length: size}, () => new Uint8Array(size));
// Finder patterns
const finder = (r, c) => {
for (let i = 0; i < 7; i++) for (let j = 0; j < 7; j++) {
mat[r+i][c+j] = (i===0||i===6||j===0||j===6||(i>=2&&i<=4&&j>=2&&j<=4)) ? 1 : 0;
}
};
finder(0, 0); finder(0, size-7); finder(size-7, 0);
// Separators
for (let i = 0; i < 8; i++) {
if (i < size) { mat[7][i]=0; mat[i][7]=0; mat[7][size-1-i]=0; mat[i][size-8]=0; mat[size-8][i]=0; mat[size-1-i][7]=0; }
}
// Timing patterns
for (let i = 8; i < size-8; i++) { mat[6][i] = i%2===0?1:0; mat[i][6] = i%2===0?1:0; }
// Alignment pattern
const ap = [[size-7, size-7]];
ap.forEach(([r,c]) => {
for (let i=-2;i<=2;i++) for(let j=-2;j<=2;j++)
mat[r+i][c+j] = (Math.abs(i)===2||Math.abs(j)===2||(!i&&!j)) ? 1:0;
});
// Data fill using seeded deterministic bits
let rng = (seed >>> 0);
const next = () => { rng = (rng * 1664525 + 1013904223) >>> 0; return rng; };
const reserved = (r,c) => {
if (r<8&&c<8) return true; if (r<8&&c>=size-8) return true;
if (r>=size-8&&c<8) return true; if (r===6||c===6) return true;
if (r>=size-9&&c>=size-9) return true;
return false;
};
// Encode actual data influence into QR
const chars = text.split('').map(c => c.charCodeAt(0));
let bitIdx = 0;
const getBit = (charPos) => {
const ch = chars[charPos % chars.length];
return (ch >> (7 - (bitIdx++ % 8))) & 1;
};
let dataPos = 0;
for (let c = size-1; c >= 0; c -= 2) {
if (c === 6) c--;
for (let r2 = 0; r2 < size; r2++) {
const r = (Math.floor((size-1-c)/2) % 2 === 0) ? size-1-r2 : r2;
for (let col = c; col > c-2 && col >= 0; col--) {
if (!reserved(r,col)) {
const bit = dataPos < chars.length * 8 ? getBit(dataPos) : (next() % 3 === 0 ? 1 : 0);
mat[r][col] = bit;
dataPos++;
}
}
}
}
// Format info strip
mat[8][0]=1;mat[8][1]=0;mat[8][2]=1;mat[8][3]=1;mat[8][4]=0;
mat[0][8]=1;mat[1][8]=0;mat[2][8]=1;mat[3][8]=1;mat[4][8]=0;
return { mat, size };
}
function toSVG(text, fg="#000", bg="#fff", px=8) {
const { mat, size } = encode(text);
const total = size * px;
const rects = [];
for (let r = 0; r < size; r++)
for (let c = 0; c < size; c++)
if (mat[r][c]) rects.push(``);
return ``;
}
return { toSVG };
})();
// ── MEMBER DATA ───────────────────────────────────────────────────────────────
const MEMBERS = [
{
id: 1, name: "Priya Sharma", email: "priya.sharma@email.com",
phone: "+91 98765 43210", rank: "Gold Achiever", role: "Team Leader",
region: "Maharashtra", city: "Mumbai", team: "Alpha Warriors",
referralCode: "PRI-2024-G441", totalPoints: 8450, activityScore: 92,
teamSize: 24, joinDate: "2024-01-15", memberSince: "Jan 2024",
avatar: "PS", status: "active", contestPoints: 1200,
badges: ["🥇", "⭐", "🔥"],
},
{
id: 2, name: "Rahul Mehta", email: "rahul.mehta@email.com",
phone: "+91 87654 32109", rank: "Diamond Leader", role: "Regional Leader",
region: "Gujarat", city: "Ahmedabad", team: "Diamond Force",
referralCode: "RAH-2023-D882", totalPoints: 6200, activityScore: 87,
teamSize: 67, joinDate: "2023-08-10", memberSince: "Aug 2023",
avatar: "RM", status: "active", contestPoints: 3400,
badges: ["💎", "👑", "🏆"],
},
{
id: 3, name: "Ananya Reddy", email: "ananya.reddy@email.com",
phone: "+91 76543 21098", rank: "Platinum Achiever", role: "Team Leader",
region: "Telangana", city: "Hyderabad", team: "Platinum Rising",
referralCode: "ANA-2024-P663", totalPoints: 4100, activityScore: 78,
teamSize: 18, joinDate: "2024-02-20", memberSince: "Feb 2024",
avatar: "AR", status: "active", contestPoints: 800,
badges: ["💠", "⭐", "🎯"],
},
{
id: 4, name: "Vikram Singh", email: "vikram.singh@email.com",
phone: "+91 65432 10987", rank: "Silver Achiever", role: "Member",
region: "Delhi NCR", city: "New Delhi", team: "Silver Surge",
referralCode: "VIK-2024-S224", totalPoints: 2800, activityScore: 65,
teamSize: 9, joinDate: "2024-04-05", memberSince: "Apr 2024",
avatar: "VS", status: "active", contestPoints: 450,
badges: ["🥈", "🎯"],
},
{
id: 5, name: "Deepika Nair", email: "deepika.nair@email.com",
phone: "+91 54321 09876", rank: "Crown Ambassador", role: "Regional Leader",
region: "Kerala", city: "Kochi", team: "Crown Elite",
referralCode: "DEE-2023-C115", totalPoints: 12400, activityScore: 98,
teamSize: 142, joinDate: "2023-11-01", memberSince: "Nov 2023",
avatar: "DN", status: "active", contestPoints: 5600,
badges: ["👑", "💎", "🏆", "🌟"],
},
];
const RANK_COLORS = {
"Starter": { from: "#4a5568", to: "#2d3748", accent: "#a0aec0" },
"Bronze Achiever": { from: "#7b3f00", to: "#4a2500", accent: "#cd7f32" },
"Silver Achiever": { from: "#2d3748", to: "#1a202c", accent: "#cbd5e0" },
"Gold Achiever": { from: "#744210", to: "#3d2008", accent: "#F6AD55" },
"Platinum Achiever": { from: "#1a365d", to: "#0f2a4a", accent: "#90cdf4" },
"Diamond Leader": { from: "#1a3a8f", to: "#0f2260", accent: "#63b3ed" },
"Crown Ambassador": { from: "#702459", to: "#44154e", accent: "#f687b3" },
"Legend Leader": { from: "#1a1a00", to: "#0d0d00", accent: "#FFD700" },
};
const getRankStyle = (rank) => RANK_COLORS[rank] || RANK_COLORS["Diamond Leader"];
const CARD_THEMES = [
{ id: "royal", label: "Royal Blue", desc: "Classic brand theme" },
{ id: "midnight", label: "Midnight", desc: "Deep prestige" },
{ id: "gold", label: "Gold Edition",desc: "Premium luxury" },
{ id: "hologram", label: "Hologram", desc: "Iridescent shimmer" },
];
// ── QR MEMBER ID CARD (front face) ───────────────────────────────────────────
function CardFront({ member, theme, width = 360 }) {
const h = width * 0.585;
const rs = getRankStyle(member.rank);
const profileUrl = `https://tagmarkets.com/member/${member.referralCode}`;
const qrSvg = QR.toSVG(profileUrl, "#fff", "transparent", 5);
const qrDataUrl = `data:image/svg+xml;base64,${btoa(qrSvg)}`;
const themes = {
royal: {
bg: `linear-gradient(135deg, #0f1e50 0%, #1a3a8f 50%, #0a1230 100%)`,
stripe: `linear-gradient(90deg, rgba(201,146,10,0) 0%, rgba(201,146,10,0.15) 50%, rgba(201,146,10,0) 100%)`,
accent: "#c9920a", accentLight: "#FFD700", textMuted: "rgba(255,255,255,0.5)",
holoBg: "rgba(255,255,255,0.04)",
},
midnight: {
bg: `linear-gradient(135deg, #050508 0%, #0d0d1a 55%, #050508 100%)`,
stripe: `linear-gradient(90deg, rgba(99,179,237,0) 0%, rgba(99,179,237,0.08) 50%, rgba(99,179,237,0) 100%)`,
accent: "#63b3ed", accentLight: "#90cdf4", textMuted: "rgba(255,255,255,0.4)",
holoBg: "rgba(99,179,237,0.04)",
},
gold: {
bg: `linear-gradient(135deg, #3d2008 0%, #7a4010 45%, #3d2008 100%)`,
stripe: `linear-gradient(90deg, rgba(255,215,0,0) 0%, rgba(255,215,0,0.12) 50%, rgba(255,215,0,0) 100%)`,
accent: "#FFD700", accentLight: "#fff7aa", textMuted: "rgba(255,255,255,0.5)",
holoBg: "rgba(255,215,10,0.06)",
},
hologram: {
bg: `linear-gradient(135deg, #0a0a1a 0%, #1a0a30 35%, #0a1a20 65%, #1a1a0a 100%)`,
stripe: `linear-gradient(90deg, rgba(240,100,200,0) 0%, rgba(100,200,240,0.1) 30%, rgba(200,240,100,0.08) 60%, rgba(240,100,200,0) 100%)`,
accent: "#e879f9", accentLight: "#f0abfc", textMuted: "rgba(255,255,255,0.5)",
holoBg: "rgba(232,121,249,0.04)",
},
};
const t = themes[theme] || themes.royal;
const scale = width / 360;
return (
{/* Animated shimmer stripe */}
{/* Subtle dot pattern */}
{/* Top gold bar */}
{/* Org name + logo row */}
T
TAG MARKETS
Success Academy
MEMBER ID
{/* Main content row */}
{/* Left: Avatar + badges */}
{/* Avatar */}
{member.avatar}
{/* Status dot */}
{/* Badges */}
{member.badges.map((b, i) => (
{b}
))}
{/* Center: Member info */}
{member.name}
{member.badges[0]}
{member.rank}
{/* Info rows */}
{[
{ label: "ROLE", value: member.role },
{ label: "REGION", value: member.region },
{ label: "TEAM", value: member.team },
{ label: "SINCE", value: member.memberSince },
].map(({ label, value }) => (
{label}
{value}
))}
{/* Points bar */}
POINTS
{member.totalPoints.toLocaleString()}
{/* Right: QR Code */}
{/* Bottom bar: ID + phone */}
MEMBER CODE
{member.referralCode}
{/* Hologram foil effect corner */}
);
}
// ── CARD BACK ─────────────────────────────────────────────────────────────────
function CardBack({ member, theme, width = 360 }) {
const h = width * 0.585;
const scale = width / 360;
const profileUrl = `https://tagmarkets.com/member/${member.referralCode}`;
const qrSvg = QR.toSVG(profileUrl, "#1a3a8f", "transparent", 7);
const qrDataUrl = `data:image/svg+xml;base64,${btoa(qrSvg)}`;
const themes = {
royal: { bg: "#0a1230", accent: "#c9920a", accentL: "#FFD700", muted: "rgba(255,255,255,0.4)" },
midnight: { bg: "#050508", accent: "#63b3ed", accentL: "#90cdf4", muted: "rgba(255,255,255,0.35)" },
gold: { bg: "#2a1005", accent: "#FFD700", accentL: "#fff7aa", muted: "rgba(255,255,255,0.4)" },
hologram: { bg: "#0a0a1a", accent: "#e879f9", accentL: "#f0abfc", muted: "rgba(255,255,255,0.4)" },
};
const t = themes[theme] || themes.royal;
return (
{/* Magnetic stripe */}
{/* Content */}
{/* Big QR */}
{/* Right info */}
VERIFICATION INFO
{[
{ label: "Full Name", value: member.name },
{ label: "Member ID", value: member.referralCode },
{ label: "Email", value: member.email },
{ label: "Activity", value: `${member.activityScore}% Score` },
{ label: "Team Size", value: `${member.teamSize} Members` },
{ label: "Points", value: member.totalPoints.toLocaleString() },
].map(({ label, value }) => (
{label.toUpperCase()}
{value}
))}
{/* Scan instruction */}
SCAN QR CODE TO VIEW LIVE PROFILE · tagmarkets.com/verify
{/* Top bar */}
T
TAG MARKETS SUCCESS ACADEMY · OFFICIAL MEMBER CARD
);
}
// ── MINI CARD (for admin grid) ────────────────────────────────────────────────
function MiniCard({ member, onClick, selected }) {
const rs = getRankStyle(member.rank);
return (
!selected && (e.currentTarget.style.borderColor = "rgba(201,146,10,0.3)")}
onMouseLeave={e => !selected && (e.currentTarget.style.borderColor = "rgba(255,255,255,0.07)")}
>
{member.avatar}
{member.name}
{member.rank}
{member.region}
{selected && (
)}
);
}
// ── STAT PILL ─────────────────────────────────────────────────────────────────
function StatPill({ value, label, icon }) {
return (
);
}
// ── MAIN APP ──────────────────────────────────────────────────────────────────
export default function QRMemberID() {
const [activeMember, setActiveMember] = useState(MEMBERS[0]);
const [theme, setTheme] = useState("royal");
const [flipped, setFlipped] = useState(false);
const [tab, setTab] = useState("card"); // card | manage | scan
const [copied, setCopied] = useState(false);
const [cardWidth, setCardWidth] = useState(380);
const [sharePopup, setSharePopup] = useState(false);
const containerRef = useRef(null);
// Responsive card width
useEffect(() => {
const obs = new ResizeObserver(([e]) => {
const w = e.contentRect.width;
setCardWidth(Math.min(Math.max(w - 48, 260), 420));
});
if (containerRef.current) obs.observe(containerRef.current);
return () => obs.disconnect();
}, []);
const handleCopyCode = () => {
navigator.clipboard?.writeText(activeMember.referralCode).catch(() => {});
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const handleDownload = () => {
alert(`📲 Downloading Member ID Card\n\nMember: ${activeMember.name}\nCode: ${activeMember.referralCode}\n\nIn production: html2canvas → PNG export\nFile: TGM-ID-${activeMember.referralCode}.png`);
};
const profileUrl = `https://tagmarkets.com/member/${activeMember.referralCode}`;
return (
{/* ── HEADER ── */}
🪪
QR Member ID
TAG Markets Success Academy
{/* Tab switcher */}
{[
{ id: "card", label: "🪪 My Card" },
{ id: "manage", label: "👥 All Members" },
{ id: "scan", label: "📡 Scanner" },
].map(t => (
))}
{/* ── CARD TAB ── */}
{tab === "card" && (
{/* Card column */}
{/* Member selector */}
Member:
{MEMBERS.map(m => (
))}
{/* 3D Flip Card */}
{/* Flip hint */}
👆 TAP CARD TO FLIP
{/* Action buttons */}
{/* Share popup */}
{sharePopup && (
Profile URL
{profileUrl}
)}
{/* Referral code */}
REFERRAL CODE
{activeMember.referralCode}
{/* Right: Theme + Stats */}
{/* Theme picker */}
Card Theme
{CARD_THEMES.map(t => (
))}
{/* Member stats */}
Member Stats
CARD INFORMATION
{[
{ label: "Joined", value: activeMember.memberSince },
{ label: "City", value: activeMember.city },
{ label: "Email", value: activeMember.email.split("@")[0] + "..." },
].map(({ label, value }) => (
{label}
{value}
))}
)}
{/* ── MANAGE TAB ── */}
{tab === "manage" && (
{/* Summary stats */}
m.status==="active").length} label="Active" icon="✅"/>
a+m.totalPoints,0).toLocaleString()} label="Total Points" icon="⭐"/>
a+m.teamSize,0)} label="Network Size" icon="🌐"/>
{/* Member grid + card preview */}
{/* Member list */}
All Members
{MEMBERS.map(m => (
{ setActiveMember(m); setFlipped(false); }}
/>
))}
{/* Card preview */}
Card Preview
)}
{/* ── SCANNER TAB ── */}
{tab === "scan" && (
📡
QR Code Scanner
Scan a member's QR code to instantly verify their identity, rank, and profile status.
{/* Fake scanner frame */}
{/* Corner brackets */}
{[["0%","0%"],["0%","auto"],["auto","0%"],["auto","auto"]].map(([t,r], i) => (
= 2 ? 8 : "auto",
left: i % 2 === 0 ? 8 : "auto", right: i % 2 === 1 ? 8 : "auto",
width: 24, height: 24,
borderTop: i < 2 ? "3px solid #c9920a" : "none",
borderBottom: i >= 2 ? "3px solid #c9920a" : "none",
borderLeft: i % 2 === 0 ? "3px solid #c9920a" : "none",
borderRight: i % 2 === 1 ? "3px solid #c9920a" : "none",
}}/>
))}
{/* Scan line animation */}
Camera Preview
or
{/* Recent scans (demo) */}
Recent Scans
{MEMBERS.slice(0, 3).map(m => (
{m.avatar}
Just now
✓ VERIFIED
))}
)}
);
}