Spaces:
Build error
Build error
<!-- src/App.svelte --> | |
<script lang="ts"> | |
import { onMount } from 'svelte'; | |
import EmailCard from './lib/EmailCard.svelte'; | |
import LoadingSpinner from './lib/LoadingSpinner.svelte'; | |
import ErrorMessage from './lib/ErrorMessage.svelte'; | |
interface Email { | |
id: string; | |
from: string; | |
subject: string; | |
body: string; | |
date: string; | |
snippet: string; | |
} | |
let emails: Email[] = []; | |
let currentIndex = 0; | |
let loading = true; | |
let error: string | null = null; | |
async function fetchEmails() { | |
try { | |
loading = true; | |
error = null; | |
// Simulated Gmail API response | |
// In a real app, you would use Google's Gmail API | |
const mockEmails: Email[] = [ | |
{ | |
id: '1', | |
from: 'GitHub <noreply@github.com>', | |
subject: 'New pull request created', | |
body: 'A new pull request has been created in the repository. Please review the changes and provide feedback.', | |
date: '2024-01-15 10:30 AM', | |
snippet: 'A new pull request has been created...' | |
}, | |
{ | |
id: '2', | |
from: 'Netflix <info@netflix.com>', | |
subject: 'New releases this week', | |
body: 'Discover the latest movies and TV shows added to Netflix this week. Don\'t miss out on the trending titles!', | |
date: '2024-01-15 9:15 AM', | |
snippet: 'Discover the latest movies and TV shows...' | |
}, | |
{ | |
id: '3', | |
from: 'Amazon <no-reply@amazon.com>', | |
subject: 'Your order has been shipped', | |
body: 'Your package is on the way! Track your order #12345-ABCD-67890 and see the estimated delivery date.', | |
date: '2024-01-15 8:45 AM', | |
snippet: 'Your package is on the way! Track your order...' | |
}, | |
{ | |
id: '4', | |
from: 'LinkedIn <updates@linkedin.com>', | |
subject: 'You have 3 new connection requests', | |
body: 'Expand your professional network by connecting with these 3 people who have requested to connect with you.', | |
date: '2024-01-14 6:20 PM', | |
snippet: 'Expand your professional network...' | |
} | |
]; | |
await new Promise(resolve => setTimeout(resolve, 1000)); | |
emails = mockEmails; | |
} catch (err) { | |
error = 'Failed to load emails. Please check your connection and try again.'; | |
} finally { | |
loading = false; | |
} | |
} | |
function nextEmail() { | |
if (currentIndex < emails.length - 1) { | |
currentIndex++; | |
} | |
} | |
function previousEmail() { | |
if (currentIndex > 0) { | |
currentIndex--; | |
} | |
} | |
onMount(() => { | |
fetchEmails(); | |
}); | |
</script> | |
<main> | |
<header> | |
<h1>Gmail Reader</h1> | |
<button | |
class="refresh-btn" | |
on:click={fetchEmails} | |
disabled={loading} | |
aria-label="Refresh emails" | |
> | |
↻ Refresh | |
</button> | |
</header> | |
{#if loading} | |
<LoadingSpinner /> | |
{:else if error} | |
<ErrorMessage {error} onRetry={fetchEmails} /> | |
{:else if emails.length === 0} | |
<div class="empty-state"> | |
<h2>No emails found</h2> | |
<p>Your inbox is empty. Check back later!</p> | |
</div> | |
{:else} | |
<div class="email-container"> | |
<EmailCard email={emails[currentIndex]} /> | |
<div class="navigation"> | |
<button | |
on:click={previousEmail} | |
disabled={currentIndex === 0} | |
aria-label="Previous email" | |
> | |
← Previous | |
</button> | |
<span class="counter"> | |
{currentIndex + 1} of {emails.length} | |
</span> | |
<button | |
on:click={nextEmail} | |
disabled={currentIndex === emails.length - 1} | |
aria-label="Next email" | |
> | |
Next → | |
</button> | |
</div> | |
</div> | |
{/if} | |
</main> |