Updated home page

This commit is contained in:
Ryahn 2025-01-31 08:06:51 -05:00
parent 4d26d024d9
commit d67c39251a
10 changed files with 212 additions and 197 deletions

View File

@ -1,13 +1,13 @@
{ {
"files": { "files": {
"main.css": "/static/css/main.f6ab033f.css", "main.css": "/static/css/main.06c3544e.css",
"main.js": "/static/js/main.4a7c450d.js", "main.js": "/static/js/main.47736d7c.js",
"index.html": "/index.html", "index.html": "/index.html",
"main.f6ab033f.css.map": "/static/css/main.f6ab033f.css.map", "main.06c3544e.css.map": "/static/css/main.06c3544e.css.map",
"main.4a7c450d.js.map": "/static/js/main.4a7c450d.js.map" "main.47736d7c.js.map": "/static/js/main.47736d7c.js.map"
}, },
"entrypoints": [ "entrypoints": [
"static/css/main.f6ab033f.css", "static/css/main.06c3544e.css",
"static/js/main.4a7c450d.js" "static/js/main.47736d7c.js"
] ]
} }

View File

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="2 Week Mail - Temporary Email Service"/><title>2 Week Mail</title><script defer="defer" src="/static/js/main.4a7c450d.js"></script><link href="/static/css/main.f6ab033f.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html> <!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="2 Week Mail - Temporary Email Service"/><title>2 Week Mail</title><script defer="defer" src="/static/js/main.47736d7c.js"></script><link href="/static/css/main.06c3544e.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"version":3,"file":"static/css/main.f6ab033f.css","mappings":"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","sources":["index.css"],"sourcesContent":["@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"],"names":[],"sourceRoot":""} {"version":3,"file":"static/css/main.06c3544e.css","mappings":"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","sources":["index.css"],"sourcesContent":["@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"],"names":[],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,46 +10,56 @@ import {
CartesianGrid, CartesianGrid,
Tooltip, Tooltip,
ResponsiveContainer ResponsiveContainer
} from 'recharts'; } from 'recharts';
import { Mail, BarChart2, ArrowRight, Loader2 } from 'lucide-react'; import { Mail, BarChart2, ArrowRight, Loader2 } from 'lucide-react';
// API endpoints - replace with your actual endpoints
const API_ENDPOINTS = { const API_ENDPOINTS = {
totalStats: '/stats/total', totalStats: '/stats/total',
timeSeriesStats: '/stats/timeseries' timeSeriesStats: '/stats/timeseries'
}; };
interface ErrorMessageProps { interface ErrorMessageProps {
message: string; message: string;
} }
interface StatsData { interface StatsData {
total: { total: {
emailsCreated: number;
messagesReceived: number;
};
timeSeriesData: Array<{
name: string;
emails: number;
messages: number;
}>;
}
interface APIResponse {
emailsCreated: number; emailsCreated: number;
messagesReceived: number; messagesReceived: number;
} };
timeSeriesData: Array<{
interface TimeSeriesDataPoint {
name: string; name: string;
emails: number; emails: number;
messages: number; messages: number;
} }>;
}
interface APIResponse {
emailsCreated: number;
messagesReceived: number;
}
interface TimeSeriesDataPoint {
name: string;
emails: number;
messages: number;
}
const Footer = () => (
<footer className="bg-gray-50 py-8">
<div className="max-w-4xl mx-auto text-center text-gray-600">
Made with{' '}
<span className="text-red-500" role="img" aria-label="heart">
</span>
{' '}by <a href="https://f95zone.to/members/ryahn.99264/" target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:text-blue-600">Ryahn</a>
</div>
</footer>
);
const App = () => { const App = () => {
const [currentPage, setCurrentPage] = useState('home'); const [currentPage, setCurrentPage] = useState('home');
const [stats, setStats] = useState({ const [stats, setStats] = useState<StatsData>({
total: { emailsCreated: 0, messagesReceived: 0 }, total: { emailsCreated: 0, messagesReceived: 0 },
timeSeriesData: [] timeSeriesData: []
}); });
@ -61,12 +71,10 @@ const App = () => {
setLoading(true); setLoading(true);
setError(null); setError(null);
// Fetch total stats
const totalResponse = await fetch(API_ENDPOINTS.totalStats); const totalResponse = await fetch(API_ENDPOINTS.totalStats);
if (!totalResponse.ok) throw new Error('Failed to fetch total stats'); if (!totalResponse.ok) throw new Error('Failed to fetch total stats');
const totalData = await totalResponse.json(); const totalData = await totalResponse.json();
// Fetch time series stats
const timeSeriesResponse = await fetch(API_ENDPOINTS.timeSeriesStats); const timeSeriesResponse = await fetch(API_ENDPOINTS.timeSeriesStats);
if (!timeSeriesResponse.ok) throw new Error('Failed to fetch time series stats'); if (!timeSeriesResponse.ok) throw new Error('Failed to fetch time series stats');
const timeSeriesData = await timeSeriesResponse.json(); const timeSeriesData = await timeSeriesResponse.json();
@ -76,18 +84,17 @@ const App = () => {
timeSeriesData: timeSeriesData timeSeriesData: timeSeriesData
}); });
} catch (err: unknown) { } catch (err: unknown) {
if (err instanceof Error) { if (err instanceof Error) {
setError(err.message); setError(err.message);
} else { } else {
setError('An unknown error occurred'); setError('An unknown error occurred');
} }
console.error('Error fetching stats:', err); console.error('Error fetching stats:', err);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
// Fetch stats on component mount and every 5 minutes
useEffect(() => { useEffect(() => {
fetchStats(); fetchStats();
const interval = setInterval(fetchStats, 5 * 60 * 1000); const interval = setInterval(fetchStats, 5 * 60 * 1000);
@ -109,172 +116,180 @@ const App = () => {
); );
const HomePage = () => ( const HomePage = () => (
<div className="min-h-screen bg-gray-50 p-8"> <div className="min-h-screen bg-gray-50 flex flex-col">
<div className="max-w-4xl mx-auto"> <div className="flex-grow p-8">
<div className="flex items-center justify-between mb-8"> <div className="max-w-4xl mx-auto">
<h1 className="text-4xl font-bold text-gray-900">2 Week Mail</h1> <div className="flex items-center justify-between mb-8">
<div className="space-x-4"> <h1 className="text-4xl font-bold text-gray-900">2 Week Mail</h1>
<Button <div className="space-x-4">
variant="ghost" <Button
className="text-gray-600 hover:text-gray-900" variant="ghost"
onClick={() => setCurrentPage('home')} className="text-gray-600 hover:text-gray-900"
> onClick={() => setCurrentPage('home')}
Home >
</Button> Home
<Button </Button>
variant="ghost" <Button
className="text-gray-600 hover:text-gray-900" variant="ghost"
onClick={() => setCurrentPage('stats')} className="text-gray-600 hover:text-gray-900"
> onClick={() => setCurrentPage('stats')}
Stats >
</Button> Stats
</Button>
</div>
</div> </div>
</div>
<Card className="mb-8"> <Card className="mb-8">
<CardContent className="pt-6"> <CardContent className="pt-6">
<div className="flex items-start space-x-4"> <div className="flex items-start space-x-4">
<div className="bg-blue-100 p-3 rounded-lg"> <div className="bg-blue-100 p-3 rounded-lg">
<Mail className="h-6 w-6 text-blue-600" /> <Mail className="h-6 w-6 text-blue-600" />
</div> </div>
<div> <div>
<h2 className="text-2xl font-semibold mb-4">Temporary Email Service</h2> <h2 className="text-2xl font-semibold mb-4">Temporary Email Service</h2>
<p className="text-gray-600 mb-4"> <p className="text-gray-600 mb-4">
Access our robust temporary email service through our API. Perfect for testing, automation, Access our robust temporary email service through our API. Perfect for testing, automation,
and temporary use cases. All emails automatically expire after 2 weeks. and temporary use cases. All emails automatically expire after 2 weeks.
</p>
<div className="bg-gray-100 p-4 rounded-lg mb-4">
<p className="text-gray-700">
Registration is currently closed. New accounts can be created upon request.
</p> </p>
<div className="bg-gray-100 p-4 rounded-lg mb-4">
<p className="text-gray-700">
Registration is currently closed. New accounts can be created upon request.
</p>
</div>
</div> </div>
</div> </div>
</div>
</CardContent>
</Card>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Card className="hover:shadow-lg transition-shadow cursor-pointer"
onClick={() => window.location.href = '/docs'}>
<CardHeader>
<CardTitle className="flex items-center space-x-2">
<span>API Documentation</span>
<ArrowRight className="h-4 w-4" />
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-600">
Comprehensive API documentation with examples and integration guides.
</p>
</CardContent> </CardContent>
</Card> </Card>
<Card <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
className="hover:shadow-lg transition-shadow cursor-pointer" <Card
onClick={() => setCurrentPage('stats')} className="hover:shadow-lg transition-shadow cursor-pointer"
> onClick={() => window.location.href = '/docs'}
<CardHeader> >
<CardTitle className="flex items-center space-x-2"> <CardHeader>
<span>Usage Statistics</span> <CardTitle className="flex items-center space-x-2">
<BarChart2 className="h-4 w-4" /> <span>API Documentation</span>
</CardTitle> <ArrowRight className="h-4 w-4" />
</CardHeader> </CardTitle>
<CardContent> </CardHeader>
<p className="text-gray-600"> <CardContent>
View real-time statistics about email creation and message reception. <p className="text-gray-600">
</p> Comprehensive API documentation with examples and integration guides.
</CardContent> </p>
</Card> </CardContent>
</Card>
<Card
className="hover:shadow-lg transition-shadow cursor-pointer"
onClick={() => setCurrentPage('stats')}
>
<CardHeader>
<CardTitle className="flex items-center space-x-2">
<span>Usage Statistics</span>
<BarChart2 className="h-4 w-4" />
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-600">
View real-time statistics about email creation and message reception.
</p>
</CardContent>
</Card>
</div>
</div> </div>
</div> </div>
<Footer />
</div> </div>
); );
const StatsPage = () => ( const StatsPage = () => (
<div className="min-h-screen bg-gray-50 p-8"> <div className="min-h-screen bg-gray-50 flex flex-col">
<div className="max-w-4xl mx-auto"> <div className="flex-grow p-8">
<div className="flex items-center justify-between mb-8"> <div className="max-w-4xl mx-auto">
<h1 className="text-4xl font-bold text-gray-900">Statistics</h1> <div className="flex items-center justify-between mb-8">
<div className="space-x-4"> <h1 className="text-4xl font-bold text-gray-900">Statistics</h1>
<Button <div className="space-x-4">
variant="ghost" <Button
className="text-gray-600 hover:text-gray-900" variant="ghost"
onClick={() => setCurrentPage('home')} className="text-gray-600 hover:text-gray-900"
> onClick={() => setCurrentPage('home')}
Home >
</Button> Home
<Button </Button>
variant="ghost" <Button
className="text-gray-600 hover:text-gray-900" variant="ghost"
onClick={() => setCurrentPage('stats')} className="text-gray-600 hover:text-gray-900"
> onClick={() => setCurrentPage('stats')}
Stats >
</Button> Stats
</div> </Button>
</div>
{error && <ErrorAlert message={error} />}
{loading ? (
<LoadingSpinner />
) : (
<>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
<Card>
<CardHeader>
<CardTitle>Total Emails Created</CardTitle>
</CardHeader>
<CardContent>
<p className="text-3xl font-bold text-blue-600">
{stats.total.emailsCreated.toLocaleString()}
</p>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Total Messages Received</CardTitle>
</CardHeader>
<CardContent>
<p className="text-3xl font-bold text-green-600">
{stats.total.messagesReceived.toLocaleString()}
</p>
</CardContent>
</Card>
</div> </div>
</div>
<Card className="mb-8"> {error && <ErrorAlert message={error} />}
<CardHeader>
<CardTitle>Weekly Activity</CardTitle> {loading ? (
</CardHeader> <LoadingSpinner />
<CardContent> ) : (
<div className="h-64"> <>
<ResponsiveContainer width="100%" height="100%"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
<LineChart data={stats.timeSeriesData} width={500} height={300}> <Card>
<CartesianGrid strokeDasharray="3 3" /> <CardHeader>
<XAxis dataKey="name" /> <CardTitle>Total Emails Created</CardTitle>
<YAxis /> </CardHeader>
<Tooltip /> <CardContent>
<Line <p className="text-3xl font-bold text-blue-600">
type="monotone" {stats.total.emailsCreated.toLocaleString()}
dataKey="emails" </p>
stroke="#2563eb" </CardContent>
name="Emails Created" </Card>
/>
<Line <Card>
type="monotone" <CardHeader>
dataKey="messages" <CardTitle>Total Messages Received</CardTitle>
stroke="#16a34a" </CardHeader>
name="Messages Received" <CardContent>
/> <p className="text-3xl font-bold text-green-600">
</LineChart> {stats.total.messagesReceived.toLocaleString()}
</ResponsiveContainer> </p>
</div> </CardContent>
</CardContent> </Card>
</Card> </div>
</>
)} <Card className="mb-8">
<CardHeader>
<CardTitle>Weekly Activity</CardTitle>
</CardHeader>
<CardContent>
<div className="h-64">
<ResponsiveContainer width="100%" height="100%">
<LineChart data={stats.timeSeriesData} width={500} height={300}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Line
type="monotone"
dataKey="emails"
stroke="#2563eb"
name="Emails Created"
/>
<Line
type="monotone"
dataKey="messages"
stroke="#16a34a"
name="Messages Received"
/>
</LineChart>
</ResponsiveContainer>
</div>
</CardContent>
</Card>
</>
)}
</div>
</div> </div>
<Footer />
</div> </div>
); );