PrithviGuardian / client /src /components /DownloadManager.tsx
Varad Bakshi
Fresh upload
e7427b5
Raw
History Blame Contribute Delete
10.1 kB
import { Download, Share2, Users, BarChart3, Palette, Settings } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { useState, useEffect } from "react";
import { storage } from "@/lib/storage";
import { userTracking, UserAnalytics } from "@/lib/userTracking";
interface AnalyticsData {
totalCalculations: number;
totalReports: number;
activeModules: string[];
lastActivity: string;
storageUsed: string;
totalSessions: number;
averageSessionTime: number;
userId: string;
}
export default function DownloadManager() {
const [analytics, setAnalytics] = useState<AnalyticsData>({
totalCalculations: 0,
totalReports: 0,
activeModules: [],
lastActivity: "Never",
storageUsed: "0 KB",
totalSessions: 0,
averageSessionTime: 0,
userId: "Loading..."
});
useEffect(() => {
loadAnalytics();
}, []);
const loadAnalytics = async () => {
try {
const calculations = await storage.getCalculations();
const reports = await storage.getReports();
const stats = await storage.getStorageStats();
const userAnalytics = userTracking.getAnalytics();
const moduleUsage = calculations.reduce((acc: Record<string, number>, calc) => {
acc[calc.module] = (acc[calc.module] || 0) + 1;
return acc;
}, {});
const lastCalc = calculations.length > 0 ?
new Date(Math.max(...calculations.map(c => new Date(c.createdAt).getTime()))).toLocaleDateString() :
"Never";
setAnalytics({
totalCalculations: calculations.length,
totalReports: reports.length,
activeModules: Object.keys(moduleUsage),
lastActivity: lastCalc,
storageUsed: stats.size,
totalSessions: userAnalytics.totalSessions,
averageSessionTime: userAnalytics.averageSessionTime,
userId: userTracking.getUserId()
});
} catch (error) {
console.error('Error loading analytics:', error);
}
};
const downloadApp = () => {
// PWA download will be handled by browser
if ('serviceWorker' in navigator) {
window.dispatchEvent(new Event('beforeinstallprompt'));
}
};
const shareApp = async () => {
const shareData = {
title: 'प्रिथ्वी Guardian AI - Environmental Engineering Assistant',
text: 'Advanced environmental engineering calculations and analysis powered by VBharat AI. Try this comprehensive offline PWA!',
url: window.location.origin
};
if (navigator.share) {
try {
await navigator.share(shareData);
} catch (error) {
console.log('Error sharing:', error);
copyToClipboard(shareData.url);
}
} else {
copyToClipboard(shareData.url);
}
};
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text).then(() => {
alert('App link copied to clipboard!');
});
};
const exportData = async () => {
try {
const data = await storage.exportData();
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `prithvi-guardian-data-${new Date().toISOString().split('T')[0]}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) {
console.error('Error exporting data:', error);
}
};
return (
<div className="space-y-6">
{/* App Download & Sharing */}
<Card className="border-l-4 border-l-saffron">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Download className="w-5 h-5 text-saffron" />
Download & Share App
</CardTitle>
<CardDescription>
Install प्रिथ्वी Guardian AI as a Progressive Web App for offline access
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Button
onClick={downloadApp}
className="bg-gradient-to-r from-saffron to-warm-orange text-white hover:from-warm-orange hover:to-saffron"
>
<Download className="w-4 h-4 mr-2" />
Install App
</Button>
<Button
onClick={shareApp}
variant="outline"
className="border-deep-green text-deep-green hover:bg-deep-green hover:text-white"
>
<Share2 className="w-4 h-4 mr-2" />
Share App
</Button>
<Button
onClick={exportData}
variant="outline"
className="border-purple-500 text-purple-500 hover:bg-purple-500 hover:text-white"
>
<Download className="w-4 h-4 mr-2" />
Export Data
</Button>
</div>
</CardContent>
</Card>
{/* User Analytics */}
<Card className="border-l-4 border-l-deep-green">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<BarChart3 className="w-5 h-5 text-deep-green" />
Usage Analytics
</CardTitle>
<CardDescription>
Track your environmental engineering work and application usage
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="text-center p-4 bg-gradient-to-br from-blue-50 to-blue-100 rounded-lg">
<div className="text-2xl font-bold text-blue-600">{analytics.totalCalculations}</div>
<div className="text-sm text-blue-700">Calculations</div>
</div>
<div className="text-center p-4 bg-gradient-to-br from-green-50 to-green-100 rounded-lg">
<div className="text-2xl font-bold text-green-600">{analytics.totalReports}</div>
<div className="text-sm text-green-700">Reports</div>
</div>
<div className="text-center p-4 bg-gradient-to-br from-purple-50 to-purple-100 rounded-lg">
<div className="text-2xl font-bold text-purple-600">{analytics.totalSessions}</div>
<div className="text-sm text-purple-700">Sessions</div>
</div>
<div className="text-center p-4 bg-gradient-to-br from-orange-50 to-orange-100 rounded-lg">
<div className="text-2xl font-bold text-orange-600">{analytics.averageSessionTime}m</div>
<div className="text-sm text-orange-700">Avg Session</div>
</div>
</div>
<div className="mt-4 grid grid-cols-2 gap-4">
<div className="p-4 bg-gray-50 rounded-lg">
<p className="text-sm text-gray-600">
<strong>User ID:</strong> {analytics.userId.slice(0, 16)}...
</p>
<p className="text-sm text-gray-600 mt-1">
<strong>Storage Used:</strong> {analytics.storageUsed}
</p>
</div>
<div className="p-4 bg-gray-50 rounded-lg">
<p className="text-sm text-gray-600">
<strong>Last Activity:</strong> {analytics.lastActivity}
</p>
<p className="text-sm text-gray-600 mt-1">
<strong>Modules Used:</strong> {analytics.activeModules.length}
</p>
</div>
</div>
<div className="mt-4 flex flex-wrap gap-2">
{analytics.activeModules.map((module, index) => (
<Badge key={index} variant="secondary" className="text-xs">
{module}
</Badge>
))}
</div>
</CardContent>
</Card>
{/* Feature List */}
<Card className="border-l-4 border-l-warm-orange">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Users className="w-5 h-5 text-warm-orange" />
Key Features
</CardTitle>
<CardDescription>
Comprehensive environmental engineering solutions powered by VBharat AI
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{[
{ title: "Air Quality Analysis", desc: "PM2.5, PM10, AQI calculations", color: "bg-blue-500" },
{ title: "Water Quality Testing", desc: "pH, BOD, COD, TDS analysis", color: "bg-cyan-500" },
{ title: "Emission Calculations", desc: "Industrial emission tracking", color: "bg-orange-500" },
{ title: "Lab Calculations", desc: "Molarity, dilution formulas", color: "bg-purple-500" },
{ title: "Weather Analysis", desc: "Meteorological calculations", color: "bg-green-500" },
{ title: "Impact Assessment", desc: "Environmental impact scoring", color: "bg-red-500" },
{ title: "PDF Reports", desc: "Professional report generation", color: "bg-indigo-500" },
{ title: "Civil Engineering", desc: "Structural calculations", color: "bg-yellow-500" },
{ title: "AI Assistant", desc: "Offline environmental Q&A", color: "bg-pink-500" }
].map((feature, index) => (
<div key={index} className="flex items-start space-x-3 p-3 rounded-lg bg-gradient-to-r from-white to-gray-50 border">
<div className={`w-3 h-3 rounded-full ${feature.color} mt-1 flex-shrink-0`}></div>
<div>
<h4 className="font-semibold text-sm text-gray-800">{feature.title}</h4>
<p className="text-xs text-gray-600">{feature.desc}</p>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
);
}