feat: implement dashboard page for QR code listing, statistics, and management.
This commit is contained in:
@@ -41,6 +41,7 @@ export default function DashboardPage() {
|
||||
totalScans: 0,
|
||||
activeQRCodes: 0,
|
||||
conversionRate: 0,
|
||||
uniqueScans: 0,
|
||||
});
|
||||
const [analyticsData, setAnalyticsData] = useState<any>(null);
|
||||
|
||||
@@ -218,13 +219,15 @@ export default function DashboardPage() {
|
||||
// Calculate real stats
|
||||
const totalScans = data.reduce((sum: number, qr: QRCodeData) => sum + (qr.scans || 0), 0);
|
||||
const activeQRCodes = data.filter((qr: QRCodeData) => qr.status === 'ACTIVE').length;
|
||||
// Calculate "Unique Rate" (Conversion)
|
||||
const conversionRate = totalScans > 0 ? Math.round((data.reduce((acc: number, qr: any) => acc + (qr.uniqueScans || 0), 0) / totalScans) * 100) : 0;
|
||||
// Calculate unique scans (absolute count)
|
||||
const uniqueScans = data.reduce((acc: number, qr: any) => acc + (qr.uniqueScans || 0), 0);
|
||||
const conversionRate = totalScans > 0 ? Math.round((uniqueScans / totalScans) * 100) : 0;
|
||||
|
||||
setStats({
|
||||
totalScans,
|
||||
activeQRCodes,
|
||||
conversionRate,
|
||||
uniqueScans,
|
||||
});
|
||||
} else {
|
||||
// If not logged in, show zeros
|
||||
@@ -233,6 +236,7 @@ export default function DashboardPage() {
|
||||
totalScans: 0,
|
||||
activeQRCodes: 0,
|
||||
conversionRate: 0,
|
||||
uniqueScans: 0,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -256,6 +260,7 @@ export default function DashboardPage() {
|
||||
totalScans: 0,
|
||||
activeQRCodes: 0,
|
||||
conversionRate: 0,
|
||||
uniqueScans: 0,
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -317,6 +322,7 @@ export default function DashboardPage() {
|
||||
totalScans: 0,
|
||||
activeQRCodes: 0,
|
||||
conversionRate: 0,
|
||||
uniqueScans: 0,
|
||||
});
|
||||
showToast(`Successfully deleted ${data.deletedCount} QR code${data.deletedCount !== 1 ? 's' : ''}`, 'success');
|
||||
} else {
|
||||
|
||||
@@ -20,6 +20,10 @@ export async function GET(request: NextRequest) {
|
||||
_count: {
|
||||
select: { scans: true },
|
||||
},
|
||||
scans: {
|
||||
where: { isUnique: true },
|
||||
select: { id: true },
|
||||
},
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
@@ -28,6 +32,7 @@ export async function GET(request: NextRequest) {
|
||||
const transformed = qrCodes.map(qr => ({
|
||||
...qr,
|
||||
scans: qr._count.scans,
|
||||
uniqueScans: qr.scans.length, // Count of scans where isUnique=true
|
||||
_count: undefined,
|
||||
}));
|
||||
|
||||
@@ -138,9 +143,9 @@ export async function POST(request: NextRequest) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let enrichedContent = body.content;
|
||||
|
||||
|
||||
// For STATIC QR codes, calculate what the QR should contain
|
||||
if (isStatic) {
|
||||
let qrContent = '';
|
||||
@@ -180,7 +185,7 @@ END:VCARD`;
|
||||
default:
|
||||
qrContent = body.content.url || 'https://example.com';
|
||||
}
|
||||
|
||||
|
||||
// Add qrContent to the content object
|
||||
enrichedContent = {
|
||||
...body.content,
|
||||
|
||||
Reference in New Issue
Block a user