chore: Docs umstrukturiert, Client-Updates, Scripts nach scripts/

This commit is contained in:
2026-01-28 20:00:37 +01:00
parent 4b38da3b85
commit 5ba12cb738
70 changed files with 1240 additions and 284 deletions

View File

@@ -1,105 +0,0 @@
# Favicon Setup Anleitung
Die Favicon-Dateien wurden erstellt. Um alle Formate zu generieren, folge diesen Schritten:
## Erstellte Dateien
`favicon.svg` - Modernes SVG Favicon (bereits erstellt)
`apple-touch-icon.svg` - SVG für Apple Touch Icon (bereits erstellt)
`site.webmanifest` - Web App Manifest (bereits erstellt)
## Noch zu erstellen (PNG/ICO)
Du musst die folgenden PNG/ICO-Dateien aus dem SVG erstellen:
### Option 1: Online Converter verwenden
1. Gehe zu einem dieser Tools:
- https://realfavicongenerator.net/ (Empfohlen - generiert alle Formate)
- https://www.zenlytools.com/svg-to-ico
- https://svg-to-ico.org/
2. Lade `favicon.svg` hoch
3. Generiere folgende Dateien:
- `favicon.ico` (16x16, 32x32, 48x48)
- `favicon-16x16.png`
- `favicon-32x32.png`
- `apple-touch-icon.png` (180x180)
- `favicon-192x192.png` (für Web Manifest)
- `favicon-512x512.png` (für Web Manifest)
4. Speichere alle generierten Dateien im `client/public/` Ordner
### Option 2: Mit ImageMagick (Command Line)
```bash
# Installiere ImageMagick (falls nicht vorhanden)
# Windows: choco install imagemagick
# Mac: brew install imagemagick
# Linux: sudo apt-get install imagemagick
cd client/public
# Erstelle PNG-Varianten
magick favicon.svg -resize 16x16 favicon-16x16.png
magick favicon.svg -resize 32x32 favicon-32x32.png
magick apple-touch-icon.svg -resize 180x180 apple-touch-icon.png
magick favicon.svg -resize 192x192 favicon-192x192.png
magick favicon.svg -resize 512x512 favicon-512x512.png
# Erstelle ICO (mehrere Größen)
magick favicon.svg -define icon:auto-resize=16,32,48 favicon.ico
```
### Option 3: Mit Online Favicon Generator (Empfohlen)
1. Gehe zu: https://realfavicongenerator.net/
2. Klicke auf "Select your Favicon image"
3. Lade `favicon.svg` hoch
4. Konfiguriere die Optionen:
- iOS: Apple Touch Icon aktivieren
- Android Chrome: Manifest aktivieren
- Windows Metro: Optional
5. Klicke auf "Generate your Favicons and HTML code"
6. Lade das ZIP herunter
7. Extrahiere alle Dateien in `client/public/`
8. Kopiere die generierten `<link>` Tags in `index.html` (falls nötig)
## Verifizierung
Nach dem Erstellen aller Dateien:
1. Starte den Dev-Server: `npm run dev`
2. Öffne die Seite im Browser
3. Prüfe den Browser-Tab - das Favicon sollte angezeigt werden
4. Teste auf Mobile:
- iOS Safari: Zum Home-Bildschirm hinzufügen → Icon sollte erscheinen
- Android Chrome: Installiere als PWA → Icon sollte erscheinen
## Dateien im public/ Ordner
Nach Abschluss sollten folgende Dateien vorhanden sein:
```
client/public/
├── favicon.svg ✅
├── favicon.ico (zu erstellen)
├── favicon-16x16.png (zu erstellen)
├── favicon-32x32.png (zu erstellen)
├── apple-touch-icon.png (zu erstellen)
├── favicon-192x192.png (zu erstellen)
├── favicon-512x512.png (zu erstellen)
├── apple-touch-icon.svg ✅
└── site.webmanifest ✅
```
## Browser-Kompatibilität
- **Chrome/Edge**: Verwendet `favicon.svg` oder `favicon.ico`
- **Firefox**: Verwendet `favicon.svg` oder `favicon.ico`
- **Safari (Desktop)**: Verwendet `favicon.ico` oder PNG
- **Safari (iOS)**: Verwendet `apple-touch-icon.png`
- **Android Chrome**: Verwendet Icons aus `site.webmanifest`
Die aktuelle Konfiguration in `index.html` unterstützt alle modernen Browser!

View File

@@ -21,10 +21,10 @@ initAnalytics()
// Loading spinner component
function LoadingSpinner() {
return (
<div className="min-h-screen flex items-center justify-center bg-slate-50">
<div className="min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900">
<div className="flex flex-col items-center gap-4">
<div className="w-10 h-10 border-4 border-primary-200 border-t-primary-600 rounded-full animate-spin" />
<p className="text-slate-500 text-sm">Loading...</p>
<div className="w-10 h-10 border-4 border-primary-200 dark:border-primary-800 border-t-primary-600 dark:border-t-primary-400 rounded-full animate-spin" />
<p className="text-slate-500 dark:text-slate-400 text-sm">Loading...</p>
</div>
</div>
)

View File

@@ -41,17 +41,17 @@ export function FAQ() {
const [openIndex, setOpenIndex] = useState<number | null>(0)
return (
<section id="faq" className="py-24 bg-slate-50">
<section id="faq" className="py-24 bg-slate-50 dark:bg-slate-900">
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Section header */}
<div className="text-center mb-16">
<div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-100 mb-6">
<HelpCircle className="w-8 h-8 text-primary-600" />
<div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-100 dark:bg-primary-900/30 mb-6">
<HelpCircle className="w-8 h-8 text-primary-600 dark:text-primary-400" />
</div>
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 mb-4">
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">
FAQ
</h2>
<p className="text-lg text-slate-600">
<p className="text-lg text-slate-600 dark:text-slate-400">
Quick answers to common questions.
</p>
</div>
@@ -70,11 +70,11 @@ export function FAQ() {
</div>
{/* Contact CTA */}
<div className="mt-12 text-center p-6 bg-white rounded-2xl border border-slate-200">
<p className="text-slate-600 mb-2">Still have questions?</p>
<div className="mt-12 text-center p-6 bg-white dark:bg-slate-800 rounded-2xl border border-slate-200 dark:border-slate-700">
<p className="text-slate-600 dark:text-slate-400 mb-2">Still have questions?</p>
<a
href="mailto:support@emailsorter.com"
className="text-primary-600 font-semibold hover:text-primary-700"
className="text-primary-600 dark:text-primary-400 font-semibold hover:text-primary-700 dark:hover:text-primary-300"
>
Contact us
</a>
@@ -93,15 +93,15 @@ interface FAQItemProps {
function FAQItem({ question, answer, isOpen, onClick }: FAQItemProps) {
return (
<div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
<div className="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden">
<button
className="w-full px-6 py-4 text-left flex items-center justify-between hover:bg-slate-50 transition-colors"
className="w-full px-6 py-4 text-left flex items-center justify-between hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors"
onClick={onClick}
>
<span className="font-semibold text-slate-900 pr-4">{question}</span>
<span className="font-semibold text-slate-900 dark:text-slate-100 pr-4">{question}</span>
<ChevronDown
className={cn(
"w-5 h-5 text-slate-400 transition-transform duration-200 flex-shrink-0",
"w-5 h-5 text-slate-400 dark:text-slate-500 transition-transform duration-200 flex-shrink-0",
isOpen && "rotate-180"
)}
/>
@@ -112,7 +112,7 @@ function FAQItem({ question, answer, isOpen, onClick }: FAQItemProps) {
isOpen ? "max-h-40" : "max-h-0"
)}
>
<p className="px-6 pb-4 text-slate-600">{answer}</p>
<p className="px-6 pb-4 text-slate-600 dark:text-slate-400">{answer}</p>
</div>
</div>
)

View File

@@ -52,17 +52,17 @@ const features = [
export function Features() {
return (
<section id="features" className="py-24 bg-slate-50">
<section id="features" className="py-24 bg-slate-50 dark:bg-slate-900">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Section header */}
<div className="text-center mb-16">
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 mb-4">
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">
Everything you need for{' '}
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary-600 to-accent-500">
Inbox Zero
</span>
</h2>
<p className="text-lg text-slate-600 max-w-2xl mx-auto">
<p className="text-lg text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
EmailSorter combines AI technology with proven email management methods
for maximum productivity.
</p>
@@ -77,17 +77,17 @@ export function Features() {
{/* Bottom illustration */}
<div className="mt-20 relative">
<div className="bg-white rounded-3xl border border-slate-200 shadow-xl p-8 max-w-4xl mx-auto">
<div className="bg-white dark:bg-slate-800 rounded-3xl border border-slate-200 dark:border-slate-700 shadow-xl p-8 max-w-4xl mx-auto">
<div className="grid md:grid-cols-3 gap-8 items-center">
{/* Before */}
<div className="text-center">
<div className="w-20 h-20 mx-auto mb-4 rounded-2xl bg-red-100 flex items-center justify-center">
<Inbox className="w-10 h-10 text-red-500" />
<div className="w-20 h-20 mx-auto mb-4 rounded-2xl bg-red-100 dark:bg-red-900/30 flex items-center justify-center">
<Inbox className="w-10 h-10 text-red-500 dark:text-red-400" />
</div>
<h4 className="font-semibold text-slate-900 mb-1">Before</h4>
<p className="text-sm text-slate-500">Inbox chaos</p>
<div className="mt-3 text-3xl font-bold text-red-500">847</div>
<p className="text-xs text-slate-400">unread emails</p>
<h4 className="font-semibold text-slate-900 dark:text-slate-100 mb-1">Before</h4>
<p className="text-sm text-slate-500 dark:text-slate-400">Inbox chaos</p>
<div className="mt-3 text-3xl font-bold text-red-500 dark:text-red-400">847</div>
<p className="text-xs text-slate-400 dark:text-slate-500">unread emails</p>
</div>
{/* Arrow */}
@@ -99,13 +99,13 @@ export function Features() {
{/* After */}
<div className="text-center">
<div className="w-20 h-20 mx-auto mb-4 rounded-2xl bg-green-100 flex items-center justify-center">
<Inbox className="w-10 h-10 text-green-500" />
<div className="w-20 h-20 mx-auto mb-4 rounded-2xl bg-green-100 dark:bg-green-900/30 flex items-center justify-center">
<Inbox className="w-10 h-10 text-green-500 dark:text-green-400" />
</div>
<h4 className="font-semibold text-slate-900 mb-1">After</h4>
<p className="text-sm text-slate-500">All sorted</p>
<div className="mt-3 text-3xl font-bold text-green-500">12</div>
<p className="text-xs text-slate-400">important emails</p>
<h4 className="font-semibold text-slate-900 dark:text-slate-100 mb-1">After</h4>
<p className="text-sm text-slate-500 dark:text-slate-400">All sorted</p>
<div className="mt-3 text-3xl font-bold text-green-500 dark:text-green-400">12</div>
<p className="text-xs text-slate-400 dark:text-slate-500">important emails</p>
</div>
</div>
</div>
@@ -129,16 +129,16 @@ function FeatureCard({ icon: Icon, title, description, color, index, highlight }
<div
className={`group rounded-2xl p-6 border transition-all duration-300 ${
highlight
? 'bg-gradient-to-br from-white to-slate-50 border-primary-200 hover:border-primary-300 hover:shadow-xl'
: 'bg-white border-slate-200 hover:border-primary-200 hover:shadow-lg'
? 'bg-gradient-to-br from-white dark:from-slate-800 to-slate-50 dark:to-slate-800/50 border-primary-200 dark:border-primary-800 hover:border-primary-300 dark:hover:border-primary-700 hover:shadow-xl'
: 'bg-white dark:bg-slate-800 border-slate-200 dark:border-slate-700 hover:border-primary-200 dark:hover:border-primary-800 hover:shadow-lg'
}`}
style={{ animationDelay: `${index * 0.1}s` }}
>
<div className={`w-14 h-14 rounded-xl bg-gradient-to-br ${color} flex items-center justify-center mb-5 group-hover:scale-110 transition-transform duration-300 shadow-lg`}>
<Icon className="w-7 h-7 text-white" />
</div>
<h3 className={`${highlight ? 'text-2xl' : 'text-xl'} font-semibold text-slate-900 mb-2`}>{title}</h3>
<p className="text-slate-600">{description}</p>
<h3 className={`${highlight ? 'text-2xl' : 'text-xl'} font-semibold text-slate-900 dark:text-slate-100 mb-2`}>{title}</h3>
<p className="text-slate-600 dark:text-slate-400">{description}</p>
</div>
)
}

View File

@@ -35,17 +35,17 @@ const steps = [
export function HowItWorks() {
return (
<section id="how-it-works" className="py-24 bg-white">
<section id="how-it-works" className="py-24 bg-white dark:bg-slate-900">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Section header */}
<div className="text-center mb-16">
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 mb-4">
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">
4 steps to a{' '}
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary-600 to-accent-500">
clean inbox
</span>
</h2>
<p className="text-lg text-slate-600 max-w-2xl mx-auto">
<p className="text-lg text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
Get started in minutes no technical knowledge required.
</p>
</div>
@@ -65,11 +65,11 @@ export function HowItWorks() {
{/* CTA */}
<div className="mt-16 text-center">
<div className="inline-flex flex-col items-center">
<ArrowDown className="w-8 h-8 text-primary-400 animate-bounce mb-4" />
<p className="text-slate-600 mb-2">Ready to get started?</p>
<ArrowDown className="w-8 h-8 text-primary-400 dark:text-primary-500 animate-bounce mb-4" />
<p className="text-slate-600 dark:text-slate-400 mb-2">Ready to get started?</p>
<a
href="/register"
className="text-primary-600 font-semibold hover:text-primary-700 transition-colors"
className="text-primary-600 dark:text-primary-400 font-semibold hover:text-primary-700 dark:hover:text-primary-300 transition-colors"
>
Try it free now
</a>
@@ -91,20 +91,20 @@ function StepCard({ icon: Icon, step, title, description }: StepCardProps) {
return (
<div className="relative">
{/* Card */}
<div className="bg-slate-50 rounded-2xl p-6 text-center hover:bg-white hover:shadow-xl transition-all duration-300 border border-transparent hover:border-slate-200">
<div className="bg-slate-50 dark:bg-slate-800 rounded-2xl p-6 text-center hover:bg-white dark:hover:bg-slate-700 hover:shadow-xl transition-all duration-300 border border-transparent hover:border-slate-200 dark:hover:border-slate-600">
{/* Step number */}
<div className="absolute -top-4 left-1/2 -translate-x-1/2 bg-gradient-to-r from-primary-500 to-primary-600 text-white text-sm font-bold px-4 py-1 rounded-full shadow-md">
<div className="absolute -top-4 left-1/2 -translate-x-1/2 bg-gradient-to-r from-primary-500 to-primary-600 dark:from-primary-600 dark:to-primary-700 text-white text-sm font-bold px-4 py-1 rounded-full shadow-md">
{step}
</div>
{/* Icon */}
<div className="w-16 h-16 mx-auto mt-4 mb-4 rounded-2xl bg-white shadow-md flex items-center justify-center">
<Icon className="w-8 h-8 text-primary-600" />
<div className="w-16 h-16 mx-auto mt-4 mb-4 rounded-2xl bg-white dark:bg-slate-700 shadow-md flex items-center justify-center">
<Icon className="w-8 h-8 text-primary-600 dark:text-primary-400" />
</div>
{/* Content */}
<h3 className="text-lg font-semibold text-slate-900 mb-2">{title}</h3>
<p className="text-slate-600 text-sm">{description}</p>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">{title}</h3>
<p className="text-slate-600 dark:text-slate-400 text-sm">{description}</p>
</div>
</div>
)

View File

@@ -64,7 +64,7 @@ export function Pricing() {
const navigate = useNavigate()
return (
<section id="pricing" className="py-24 bg-slate-50">
<section id="pricing" className="py-24 bg-slate-50 dark:bg-slate-900">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Section header */}
<div className="text-center mb-16">
@@ -72,10 +72,10 @@ export function Pricing() {
<Sparkles className="w-3 h-3 mr-1" />
14-day free trial
</Badge>
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 mb-4">
<h2 className="text-3xl sm:text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">
Simple, transparent pricing
</h2>
<p className="text-lg text-slate-600 max-w-2xl mx-auto">
<p className="text-lg text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
Choose the plan that fits you. Cancel anytime, no hidden costs.
</p>
</div>
@@ -93,11 +93,11 @@ export function Pricing() {
{/* FAQ teaser */}
<div className="mt-16 text-center">
<p className="text-slate-600">
<p className="text-slate-600 dark:text-slate-400">
Still have questions?{' '}
<button
onClick={() => document.getElementById('faq')?.scrollIntoView({ behavior: 'smooth' })}
className="text-primary-600 font-semibold hover:text-primary-700"
className="text-primary-600 dark:text-primary-400 font-semibold hover:text-primary-700 dark:hover:text-primary-300"
>
Check our FAQ
</button>
@@ -131,15 +131,15 @@ function PricingCard({
}: PricingCardProps) {
return (
<div
className={`relative bg-white rounded-2xl p-8 ${
className={`relative bg-white dark:bg-slate-800 rounded-2xl p-8 ${
popular
? 'ring-2 ring-primary-500 shadow-xl scale-105'
: 'border border-slate-200 hover:border-primary-200 hover:shadow-lg'
? 'ring-2 ring-primary-500 dark:ring-primary-400 shadow-xl scale-105'
: 'border border-slate-200 dark:border-slate-700 hover:border-primary-200 dark:hover:border-primary-800 hover:shadow-lg'
} transition-all duration-300`}
>
{popular && (
<div className="absolute -top-4 left-1/2 -translate-x-1/2">
<Badge className="bg-primary-500 text-white border-0 shadow-md">
<Badge className="bg-primary-500 dark:bg-primary-600 text-white border-0 shadow-md">
Most Popular
</Badge>
</div>
@@ -147,15 +147,15 @@ function PricingCard({
{/* Header */}
<div className="text-center mb-6">
<h3 className="text-xl font-bold text-slate-900 mb-1">{name}</h3>
<p className="text-sm text-slate-500">{description}</p>
<h3 className="text-xl font-bold text-slate-900 dark:text-slate-100 mb-1">{name}</h3>
<p className="text-sm text-slate-500 dark:text-slate-400">{description}</p>
</div>
{/* Price */}
<div className="text-center mb-8">
<div className="flex items-baseline justify-center">
<span className="text-5xl font-extrabold text-slate-900">${price}</span>
<span className="text-slate-500 ml-1">{period}</span>
<span className="text-5xl font-extrabold text-slate-900 dark:text-slate-100">${price}</span>
<span className="text-slate-500 dark:text-slate-400 ml-1">{period}</span>
</div>
</div>
@@ -164,15 +164,15 @@ function PricingCard({
{features.map((feature, index) => (
<li key={index} className="flex items-center gap-3">
{feature.included ? (
<div className="w-5 h-5 rounded-full bg-green-100 flex items-center justify-center flex-shrink-0">
<Check className="w-3 h-3 text-green-600" />
<div className="w-5 h-5 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center flex-shrink-0">
<Check className="w-3 h-3 text-green-600 dark:text-green-400" />
</div>
) : (
<div className="w-5 h-5 rounded-full bg-slate-100 flex items-center justify-center flex-shrink-0">
<X className="w-3 h-3 text-slate-400" />
<div className="w-5 h-5 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center flex-shrink-0">
<X className="w-3 h-3 text-slate-400 dark:text-slate-500" />
</div>
)}
<span className={feature.included ? 'text-slate-700' : 'text-slate-400'}>
<span className={feature.included ? 'text-slate-700 dark:text-slate-300' : 'text-slate-400 dark:text-slate-500'}>
{feature.text}
</span>
</li>

View File

@@ -18,9 +18,19 @@ export { ID }
export const auth = {
// Create a new account
async register(email: string, password: string, name?: string) {
const user = await account.create(ID.unique(), email, password, name)
await this.login(email, password)
return user
// #region agent log
fetch('http://127.0.0.1:7242/ingest/4fa7412d-6f79-4871-8728-29c37c9e5772',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'appwrite.ts:20',message:'register called',data:{endpoint:APPWRITE_ENDPOINT,origin:window.location.origin,email},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
// #endregion
try {
const user = await account.create(ID.unique(), email, password, name)
await this.login(email, password)
return user
} catch (error) {
// #region agent log
fetch('http://127.0.0.1:7242/ingest/4fa7412d-6f79-4871-8728-29c37c9e5772',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'appwrite.ts:23',message:'register error',data:{errorMessage:error instanceof Error ? error.message : 'Unknown error'},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
// #endregion
throw error
}
},
// Login with email and password

View File

@@ -29,22 +29,22 @@ export function ForgotPassword() {
}
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 flex items-center justify-center p-4">
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800 flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* Logo */}
<Link to="/" className="flex items-center justify-center gap-2 mb-8">
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-primary-500 to-primary-700 flex items-center justify-center">
<Mail className="w-5 h-5 text-white" />
</div>
<span className="text-xl font-bold text-slate-900">
Email<span className="text-primary-600">Sorter</span>
<span className="text-xl font-bold text-slate-900 dark:text-slate-100">
Email<span className="text-primary-600 dark:text-primary-400">Sorter</span>
</span>
</Link>
<Card className="shadow-xl border-0">
<Card className="shadow-xl border-0 dark:bg-slate-800 dark:border-slate-700">
<CardHeader className="text-center pb-2">
<CardTitle className="text-2xl">Passwort vergessen?</CardTitle>
<CardDescription>
<CardTitle className="text-2xl dark:text-slate-100">Passwort vergessen?</CardTitle>
<CardDescription className="dark:text-slate-400">
{sent
? 'Prüfe dein E-Mail-Postfach'
: 'Gib deine E-Mail-Adresse ein und wir senden dir einen Link zum Zurücksetzen.'
@@ -54,14 +54,14 @@ export function ForgotPassword() {
<CardContent>
{sent ? (
<div className="text-center py-8">
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-8 h-8 text-green-600" />
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center">
<CheckCircle className="w-8 h-8 text-green-600 dark:text-green-400" />
</div>
<h3 className="font-semibold text-slate-900 mb-2">E-Mail gesendet!</h3>
<p className="text-slate-600 mb-6">
Wir haben dir eine E-Mail mit einem Link zum Zurücksetzen deines Passworts an <strong>{email}</strong> gesendet.
<h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-2">E-Mail gesendet!</h3>
<p className="text-slate-600 dark:text-slate-400 mb-6">
Wir haben dir eine E-Mail mit einem Link zum Zurücksetzen deines Passworts an <strong className="text-slate-900 dark:text-slate-100">{email}</strong> gesendet.
</p>
<p className="text-sm text-slate-500 mb-6">
<p className="text-sm text-slate-500 dark:text-slate-400 mb-6">
Keine E-Mail erhalten? Prüfe deinen Spam-Ordner oder versuche es erneut.
</p>
<div className="space-y-3">
@@ -83,13 +83,13 @@ export function ForgotPassword() {
) : (
<form onSubmit={handleSubmit} className="space-y-6">
{error && (
<div className="p-3 bg-red-50 border border-red-200 rounded-lg text-red-700 text-sm">
<div className="p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg text-red-700 dark:text-red-300 text-sm">
{error}
</div>
)}
<div className="space-y-2">
<Label htmlFor="email">E-Mail-Adresse</Label>
<Label htmlFor="email" className="dark:text-slate-200">E-Mail-Adresse</Label>
<Input
id="email"
type="email"
@@ -98,6 +98,7 @@ export function ForgotPassword() {
onChange={(e) => setEmail(e.target.value)}
required
autoFocus
className="dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100"
/>
</div>
@@ -115,7 +116,7 @@ export function ForgotPassword() {
<div className="text-center">
<Link
to="/login"
className="text-sm text-primary-600 hover:text-primary-700"
className="text-sm text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300"
>
<ArrowLeft className="w-4 h-4 inline mr-1" />
Zurück zum Login

View File

@@ -3,7 +3,7 @@ import { ArrowLeft, Building2 } from 'lucide-react'
export function Imprint() {
return (
<div className="min-h-screen bg-slate-50">
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
{/* Header */}
<header className="bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-700">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
@@ -19,56 +19,56 @@ export function Imprint() {
{/* Content */}
<main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-8 md:p-12">
<div className="bg-white dark:bg-slate-800 rounded-xl shadow-sm border border-slate-200 dark:border-slate-700 p-8 md:p-12">
{/* Title */}
<div className="flex items-center gap-3 mb-8">
<div className="w-12 h-12 rounded-lg bg-primary-100 flex items-center justify-center">
<Building2 className="w-6 h-6 text-primary-600" />
<div className="w-12 h-12 rounded-lg bg-primary-100 dark:bg-primary-900/30 flex items-center justify-center">
<Building2 className="w-6 h-6 text-primary-600 dark:text-primary-400" />
</div>
<div>
<h1 className="text-3xl font-bold text-slate-900">Impressum</h1>
<p className="text-slate-500 mt-1">Legal Information</p>
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100">Impressum</h1>
<p className="text-slate-500 dark:text-slate-400 mt-1">Legal Information</p>
</div>
</div>
{/* Content - Placeholder for webklar.com content */}
<div className="prose prose-slate max-w-none">
<p className="text-slate-600 mb-6">
<div className="prose prose-slate max-w-none dark:prose-invert">
<p className="text-slate-600 dark:text-slate-400 mb-6">
<strong>Note:</strong> This imprint is managed by webklar.com. Please refer to their imprint for detailed information.
</p>
<div className="bg-slate-50 border border-slate-200 rounded-lg p-6 mb-8">
<h2 className="text-xl font-semibold text-slate-900 mb-4">Information according to § 5 TMG</h2>
<div className="bg-slate-50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-6 mb-8">
<h2 className="text-xl font-semibold text-slate-900 dark:text-slate-100 mb-4">Information according to § 5 TMG</h2>
<div className="space-y-6 text-slate-700">
<div className="space-y-6 text-slate-700 dark:text-slate-300">
<div>
<h3 className="text-lg font-semibold text-slate-900 mb-2">Operator</h3>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">Operator</h3>
<p className="mb-2">EmailSorter is operated by:</p>
<p className="mb-4">
<strong>webklar.com</strong><br />
Kenso Grimm, Justin Klein
</p>
<p className="text-sm text-slate-600 mb-4">
<p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
For complete contact details and legal information, please visit:{' '}
<a
href="https://webklar.com/impressum"
target="_blank"
rel="noopener noreferrer"
className="text-primary-600 hover:text-primary-700 underline"
className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline"
>
webklar.com/impressum
</a>
</p>
</div>
<div className="pt-6 border-t border-slate-200">
<h3 className="text-lg font-semibold text-slate-900 mb-2">Contact</h3>
<div className="pt-6 border-t border-slate-200 dark:border-slate-700">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">Contact</h3>
<div className="space-y-2">
<p>
<strong>Email:</strong>{' '}
<a
href="mailto:support@webklar.com"
className="text-primary-600 hover:text-primary-700 underline"
className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline"
>
support@webklar.com
</a>
@@ -77,23 +77,23 @@ export function Imprint() {
<strong>Phone:</strong>{' '}
<a
href="tel:+4917623726355"
className="text-primary-600 hover:text-primary-700 underline"
className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline"
>
+49 176 23726355
</a>
{' / '}
<a
href="tel:+491704969375"
className="text-primary-600 hover:text-primary-700 underline"
className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline"
>
+49 170 4969375
</a>
</p>
<p className="mt-4 text-sm text-slate-600">
<p className="mt-4 text-sm text-slate-600 dark:text-slate-400">
For questions regarding EmailSorter specifically:{' '}
<a
href="mailto:support@emailsorter.com"
className="text-primary-600 hover:text-primary-700 underline"
className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline"
>
support@emailsorter.com
</a>
@@ -101,8 +101,8 @@ export function Imprint() {
</div>
</div>
<div className="pt-6 border-t border-slate-200">
<h3 className="text-lg font-semibold text-slate-900 mb-2">Responsible for Content</h3>
<div className="pt-6 border-t border-slate-200 dark:border-slate-700">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">Responsible for Content</h3>
<p>
The content of this website is the responsibility of webklar.com.
For detailed information, please refer to the official imprint at{' '}
@@ -110,23 +110,23 @@ export function Imprint() {
href="https://webklar.com/impressum"
target="_blank"
rel="noopener noreferrer"
className="text-primary-600 hover:text-primary-700 underline"
className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline"
>
webklar.com/impressum
</a>
</p>
</div>
<div className="pt-6 border-t border-slate-200">
<h3 className="text-lg font-semibold text-slate-900 mb-2">Liability for Links</h3>
<div className="pt-6 border-t border-slate-200 dark:border-slate-700">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">Liability for Links</h3>
<p>
Our website contains links to external websites. We have no influence on the content of these websites.
Therefore, we cannot assume any liability for these external contents.
</p>
</div>
<div className="pt-6 border-t border-slate-200">
<h3 className="text-lg font-semibold text-slate-900 mb-2">Copyright</h3>
<div className="pt-6 border-t border-slate-200 dark:border-slate-700">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">Copyright</h3>
<p>
The content and works on this website are subject to German copyright law.
Reproduction, processing, distribution, and any form of commercialization require the written consent of the respective author or creator.
@@ -134,14 +134,14 @@ export function Imprint() {
</div>
</div>
<div className="mt-8 pt-6 border-t border-slate-200">
<p className="text-sm text-slate-500">
<div className="mt-8 pt-6 border-t border-slate-200 dark:border-slate-700">
<p className="text-sm text-slate-500 dark:text-slate-400">
<strong>Important:</strong> This is a simplified version. For the complete and legally binding imprint, please visit{' '}
<a
href="https://webklar.com/impressum"
target="_blank"
rel="noopener noreferrer"
className="text-primary-600 hover:text-primary-700 underline"
className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline"
>
webklar.com/impressum
</a>

View File

@@ -3,7 +3,7 @@ import { ArrowLeft, Shield } from 'lucide-react'
export function Privacy() {
return (
<div className="min-h-screen bg-slate-50">
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
{/* Header */}
<header className="bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-700">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
@@ -19,81 +19,81 @@ export function Privacy() {
{/* Content */}
<main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-8 md:p-12">
<div className="bg-white dark:bg-slate-800 rounded-xl shadow-sm border border-slate-200 dark:border-slate-700 p-8 md:p-12">
{/* Title */}
<div className="flex items-center gap-3 mb-8">
<div className="w-12 h-12 rounded-lg bg-primary-100 flex items-center justify-center">
<Shield className="w-6 h-6 text-primary-600" />
<div className="w-12 h-12 rounded-lg bg-primary-100 dark:bg-primary-900/30 flex items-center justify-center">
<Shield className="w-6 h-6 text-primary-600 dark:text-primary-400" />
</div>
<div>
<h1 className="text-3xl font-bold text-slate-900">Privacy Policy</h1>
<p className="text-slate-500 mt-1">Last updated: {new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}</p>
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100">Privacy Policy</h1>
<p className="text-slate-500 dark:text-slate-400 mt-1">Last updated: {new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}</p>
</div>
</div>
{/* Content - Placeholder for webklar.com content */}
<div className="prose prose-slate max-w-none">
<p className="text-slate-600 mb-6">
<div className="prose prose-slate max-w-none dark:prose-invert">
<p className="text-slate-600 dark:text-slate-400 mb-6">
<strong>Note:</strong> This privacy policy is managed by webklar.com. Please refer to their privacy policy for detailed information.
</p>
<div className="bg-slate-50 border border-slate-200 rounded-lg p-6 mb-8">
<h2 className="text-xl font-semibold text-slate-900 mb-4">Data Protection Information</h2>
<p className="text-slate-700 mb-4">
<div className="bg-slate-50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-6 mb-8">
<h2 className="text-xl font-semibold text-slate-900 dark:text-slate-100 mb-4">Data Protection Information</h2>
<p className="text-slate-700 dark:text-slate-300 mb-4">
EmailSorter is operated by webklar.com. The following privacy policy applies to the use of this website and our services.
</p>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">1. Responsible Party</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">1. Responsible Party</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
The responsible party for data processing on this website is:
</p>
<div className="bg-white border border-slate-200 rounded-lg p-4 mb-4">
<p className="text-slate-700 mb-2">
<div className="bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg p-4 mb-4">
<p className="text-slate-700 dark:text-slate-300 mb-2">
<strong>webklar.com</strong><br />
Kenso Grimm, Justin Klein
</p>
<p className="text-slate-700 mb-2">
<p className="text-slate-700 dark:text-slate-300 mb-2">
<strong>Contact:</strong><br />
Email: <a href="mailto:support@webklar.com" className="text-primary-600 hover:text-primary-700 underline">support@webklar.com</a><br />
Phone: <a href="tel:+4917623726355" className="text-primary-600 hover:text-primary-700 underline">+49 176 23726355</a>
Email: <a href="mailto:support@webklar.com" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline">support@webklar.com</a><br />
Phone: <a href="tel:+4917623726355" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline">+49 176 23726355</a>
</p>
<p className="text-sm text-slate-600 mt-3">
For complete contact details, please refer to the <Link to="/imprint" className="text-primary-600 hover:text-primary-700 underline">Impressum</Link>.
<p className="text-sm text-slate-600 dark:text-slate-400 mt-3">
For complete contact details, please refer to the <Link to="/imprint" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline">Impressum</Link>.
</p>
</div>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">2. Data Collection and Processing</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">2. Data Collection and Processing</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
When you use EmailSorter, we collect and process the following data:
</p>
<ul className="list-disc list-inside text-slate-700 mb-4 space-y-2 ml-4">
<ul className="list-disc list-inside text-slate-700 dark:text-slate-300 mb-4 space-y-2 ml-4">
<li>Account information (email address, name)</li>
<li>Email metadata (sender, subject, date) for sorting purposes</li>
<li>Usage statistics and preferences</li>
<li>Payment information (processed securely via Stripe)</li>
</ul>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">3. Purpose of Data Processing</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">3. Purpose of Data Processing</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
We process your data exclusively for the following purposes:
</p>
<ul className="list-disc list-inside text-slate-700 mb-4 space-y-2 ml-4">
<ul className="list-disc list-inside text-slate-700 dark:text-slate-300 mb-4 space-y-2 ml-4">
<li>Providing and improving the EmailSorter service</li>
<li>Automated email sorting and categorization</li>
<li>Processing payments and subscriptions</li>
<li>Customer support and communication</li>
</ul>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">4. Data Security</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">4. Data Security</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
We implement appropriate technical and organizational measures to protect your data against unauthorized access, loss, or destruction.
</p>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">5. Your Rights</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">5. Your Rights</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
You have the right to:
</p>
<ul className="list-disc list-inside text-slate-700 mb-4 space-y-2 ml-4">
<ul className="list-disc list-inside text-slate-700 dark:text-slate-300 mb-4 space-y-2 ml-4">
<li>Access your personal data</li>
<li>Correct inaccurate data</li>
<li>Request deletion of your data</li>
@@ -101,14 +101,14 @@ export function Privacy() {
<li>Data portability</li>
</ul>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">6. Hosting and Third-Party Services</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">6. Hosting and Third-Party Services</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
<strong>Hosting:</strong> Our website is hosted by Netlify, which acts as a data processor.
</p>
<p className="text-slate-700 mb-4">
<p className="text-slate-700 dark:text-slate-300 mb-4">
We use the following third-party services:
</p>
<ul className="list-disc list-inside text-slate-700 mb-4 space-y-2 ml-4">
<ul className="list-disc list-inside text-slate-700 dark:text-slate-300 mb-4 space-y-2 ml-4">
<li><strong>Appwrite:</strong> User authentication and database</li>
<li><strong>Stripe:</strong> Payment processing</li>
<li><strong>Mistral AI:</strong> Email categorization</li>
@@ -116,45 +116,45 @@ export function Privacy() {
<li><strong>Plausible (optional):</strong> Privacy-friendly analytics tool, if enabled</li>
</ul>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">6.1. Cookies and Tracking</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">6.1. Cookies and Tracking</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
We do not use external fonts or unnecessary cookies. If we use any tracking tools (such as Plausible),
they are privacy-friendly and do not store personal data. We only process personal data to the extent
that it is technically or organizationally necessary.
</p>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">7. Contact Form Data</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">7. Contact Form Data</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
Data that you send to us via contact forms will be stored and used for processing your inquiry.
This data will not be shared with third parties without your consent.
</p>
<h3 className="text-lg font-semibold text-slate-900 mt-6 mb-3">8. Contact</h3>
<p className="text-slate-700 mb-4">
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mt-6 mb-3">8. Contact</h3>
<p className="text-slate-700 dark:text-slate-300 mb-4">
For questions regarding data protection, please contact us:
</p>
<div className="bg-white border border-slate-200 rounded-lg p-4 mb-4">
<p className="text-slate-700">
<div className="bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg p-4 mb-4">
<p className="text-slate-700 dark:text-slate-300">
<strong>Email:</strong>{' '}
<a href="mailto:support@webklar.com" className="text-primary-600 hover:text-primary-700 underline">
<a href="mailto:support@webklar.com" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline">
support@webklar.com
</a>
</p>
<p className="text-slate-700 mt-2">
<p className="text-slate-700 dark:text-slate-300 mt-2">
<strong>Phone:</strong>{' '}
<a href="tel:+4917623726355" className="text-primary-600 hover:text-primary-700 underline">
<a href="tel:+4917623726355" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline">
+49 176 23726355
</a>
</p>
<p className="text-sm text-slate-600 mt-3">
For complete contact details, please refer to the <Link to="/imprint" className="text-primary-600 hover:text-primary-700 underline">Impressum</Link>.
<p className="text-sm text-slate-600 dark:text-slate-400 mt-3">
For complete contact details, please refer to the <Link to="/imprint" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline">Impressum</Link>.
</p>
</div>
<div className="mt-8 pt-6 border-t border-slate-200">
<p className="text-sm text-slate-500">
<div className="mt-8 pt-6 border-t border-slate-200 dark:border-slate-700">
<p className="text-sm text-slate-500 dark:text-slate-400">
<strong>Important:</strong> This is a simplified version. For the complete and legally binding privacy policy, please visit{' '}
<a href="https://webklar.com/datenschutz" target="_blank" rel="noopener noreferrer" className="text-primary-600 hover:text-primary-700 underline">
<a href="https://webklar.com/datenschutz" target="_blank" rel="noopener noreferrer" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 underline">
webklar.com/datenschutz
</a>
</p>

View File

@@ -114,30 +114,30 @@ export function Register() {
</div>
{/* Right side - Form */}
<div className="flex-1 flex items-center justify-center px-4 sm:px-6 lg:px-8 bg-white">
<div className="flex-1 flex items-center justify-center px-4 sm:px-6 lg:px-8 bg-white dark:bg-slate-900">
<div className="w-full max-w-md">
{/* Logo */}
<Link to="/" className="flex items-center gap-2 mb-8">
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-primary-500 to-primary-700 flex items-center justify-center">
<Mail className="w-5 h-5 text-white" />
</div>
<span className="text-xl font-bold text-slate-900">
E-Mail-<span className="text-primary-600">Sorter</span>
<span className="text-xl font-bold text-slate-900 dark:text-slate-100">
E-Mail-<span className="text-primary-600 dark:text-primary-400">Sorter</span>
</span>
</Link>
<h1 className="text-3xl font-bold text-slate-900 mb-2">
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100 mb-2">
Create account
</h1>
<p className="text-slate-600 mb-8">
<p className="text-slate-600 dark:text-slate-400 mb-8">
Ready to go in less than a minute.
</p>
{/* Error message */}
{error && (
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-xl flex items-start gap-3">
<AlertCircle className="w-5 h-5 text-red-500 flex-shrink-0 mt-0.5" />
<p className="text-sm text-red-600">{error}</p>
<div className="mb-6 p-4 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-xl flex items-start gap-3">
<AlertCircle className="w-5 h-5 text-red-500 dark:text-red-400 flex-shrink-0 mt-0.5" />
<p className="text-sm text-red-600 dark:text-red-300">{error}</p>
</div>
)}
@@ -217,16 +217,16 @@ export function Register() {
)}
</Button>
<p className="text-xs text-slate-500 text-center">
<p className="text-xs text-slate-500 dark:text-slate-400 text-center">
By signing up, you agree to our{' '}
<a href="#" className="text-primary-600 hover:underline">Terms of Service</a> and{' '}
<a href="#" className="text-primary-600 hover:underline">Privacy Policy</a>.
<a href="#" className="text-primary-600 dark:text-primary-400 hover:underline">Terms of Service</a> and{' '}
<a href="#" className="text-primary-600 dark:text-primary-400 hover:underline">Privacy Policy</a>.
</p>
</form>
<p className="mt-8 text-center text-slate-600">
<p className="mt-8 text-center text-slate-600 dark:text-slate-400">
Already have an account?{' '}
<Link to="/login" className="text-primary-600 font-semibold hover:text-primary-700">
<Link to="/login" className="text-primary-600 dark:text-primary-400 font-semibold hover:text-primary-700 dark:hover:text-primary-300">
Sign in
</Link>
</p>

View File

@@ -83,24 +83,24 @@ export function ResetPassword() {
const passwordStrength = getPasswordStrength()
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 flex items-center justify-center p-4">
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800 flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* Logo */}
<Link to="/" className="flex items-center justify-center gap-2 mb-8">
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-primary-500 to-primary-700 flex items-center justify-center">
<Mail className="w-5 h-5 text-white" />
</div>
<span className="text-xl font-bold text-slate-900">
Email<span className="text-primary-600">Sorter</span>
<span className="text-xl font-bold text-slate-900 dark:text-slate-100">
Email<span className="text-primary-600 dark:text-primary-400">Sorter</span>
</span>
</Link>
<Card className="shadow-xl border-0">
<Card className="shadow-xl border-0 dark:bg-slate-800 dark:border-slate-700">
<CardHeader className="text-center pb-2">
<CardTitle className="text-2xl">
<CardTitle className="text-2xl dark:text-slate-100">
{success ? 'Passwort geändert!' : 'Neues Passwort festlegen'}
</CardTitle>
<CardDescription>
<CardDescription className="dark:text-slate-400">
{success
? 'Dein Passwort wurde erfolgreich geändert.'
: 'Wähle ein sicheres neues Passwort für deinen Account.'
@@ -110,10 +110,10 @@ export function ResetPassword() {
<CardContent>
{success ? (
<div className="text-center py-8">
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-8 h-8 text-green-600" />
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center">
<CheckCircle className="w-8 h-8 text-green-600 dark:text-green-400" />
</div>
<p className="text-slate-600 mb-6">
<p className="text-slate-600 dark:text-slate-400 mb-6">
Du kannst dich jetzt mit deinem neuen Passwort anmelden.
</p>
<Button onClick={() => navigate('/login')} className="w-full">
@@ -122,11 +122,11 @@ export function ResetPassword() {
</div>
) : !userId || !secret ? (
<div className="text-center py-8">
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-red-100 flex items-center justify-center">
<XCircle className="w-8 h-8 text-red-600" />
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center">
<XCircle className="w-8 h-8 text-red-600 dark:text-red-400" />
</div>
<h3 className="font-semibold text-slate-900 mb-2">Ungültiger Link</h3>
<p className="text-slate-600 mb-6">
<h3 className="font-semibold text-slate-900 dark:text-slate-100 mb-2">Ungültiger Link</h3>
<p className="text-slate-600 dark:text-slate-400 mb-6">
Dieser Link zum Zurücksetzen des Passworts ist ungültig oder abgelaufen.
</p>
<Link to="/forgot-password">
@@ -136,13 +136,13 @@ export function ResetPassword() {
) : (
<form onSubmit={handleSubmit} className="space-y-6">
{error && (
<div className="p-3 bg-red-50 border border-red-200 rounded-lg text-red-700 text-sm">
<div className="p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg text-red-700 dark:text-red-300 text-sm">
{error}
</div>
)}
<div className="space-y-2">
<Label htmlFor="password">Neues Passwort</Label>
<Label htmlFor="password" className="dark:text-slate-200">Neues Passwort</Label>
<div className="relative">
<Input
id="password"
@@ -152,11 +152,12 @@ export function ResetPassword() {
onChange={(e) => setPassword(e.target.value)}
required
autoFocus
className="dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600"
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 dark:text-slate-500 hover:text-slate-600 dark:hover:text-slate-300"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
@@ -172,13 +173,13 @@ export function ResetPassword() {
className={`h-1 flex-1 rounded-full transition-colors ${
level <= passwordStrength.strength
? passwordStrength.color
: 'bg-slate-200'
: 'bg-slate-200 dark:bg-slate-700'
}`}
/>
))}
</div>
<p className={`text-xs ${
passwordStrength.strength < 3 ? 'text-red-500' : 'text-green-600'
passwordStrength.strength < 3 ? 'text-red-500 dark:text-red-400' : 'text-green-600 dark:text-green-400'
}`}>
{passwordStrength.label}
</p>
@@ -187,7 +188,7 @@ export function ResetPassword() {
</div>
<div className="space-y-2">
<Label htmlFor="confirmPassword">Passwort bestätigen</Label>
<Label htmlFor="confirmPassword" className="dark:text-slate-200">Passwort bestätigen</Label>
<Input
id="confirmPassword"
type={showPassword ? 'text' : 'password'}
@@ -195,9 +196,10 @@ export function ResetPassword() {
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
className="dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100"
/>
{confirmPassword && password !== confirmPassword && (
<p className="text-xs text-red-500">Passwörter stimmen nicht überein</p>
<p className="text-xs text-red-500 dark:text-red-400">Passwörter stimmen nicht überein</p>
)}
</div>

View File

@@ -283,17 +283,17 @@ export function Setup() {
// Show loading while checking accounts
if (checkingAccounts) {
return (
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-white flex items-center justify-center">
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-white dark:from-slate-900 dark:to-slate-800 flex items-center justify-center">
<div className="text-center">
<Loader2 className="w-8 h-8 animate-spin text-primary-600 mx-auto mb-4" />
<p className="text-slate-600">Setting up your account...</p>
<Loader2 className="w-8 h-8 animate-spin text-primary-600 dark:text-primary-400 mx-auto mb-4" />
<p className="text-slate-600 dark:text-slate-400">Setting up your account...</p>
</div>
</div>
)
}
return (
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-white">
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-white dark:from-slate-900 dark:to-slate-800">
<header className="bg-white/80 dark:bg-slate-900/80 backdrop-blur-sm border-b border-slate-200 dark:border-slate-700 sticky top-0 z-40">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div className="flex items-center justify-between">
@@ -315,13 +315,13 @@ export function Setup() {
{/* Success message after checkout */}
{isFromCheckout && (
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 pt-8">
<div className="bg-green-50 border border-green-200 rounded-xl p-6 mb-6 flex items-start gap-4">
<div className="w-10 h-10 rounded-full bg-green-500 flex items-center justify-center flex-shrink-0">
<div className="bg-green-50 dark:bg-green-900/30 border border-green-200 dark:border-green-800 rounded-xl p-6 mb-6 flex items-start gap-4">
<div className="w-10 h-10 rounded-full bg-green-500 dark:bg-green-600 flex items-center justify-center flex-shrink-0">
<Check className="w-6 h-6 text-white" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-green-900 mb-1">Payment successful!</h3>
<p className="text-sm text-green-700">
<h3 className="font-semibold text-green-900 dark:text-green-200 mb-1">Payment successful!</h3>
<p className="text-sm text-green-700 dark:text-green-300">
Your subscription is active. Let's connect your email account to get started.
</p>
</div>
@@ -351,23 +351,23 @@ export function Setup() {
<div
className={`w-10 h-10 rounded-full flex items-center justify-center text-sm font-semibold transition-all duration-300 ${
index < stepIndex
? 'bg-green-500 text-white shadow-lg shadow-green-500/30'
? 'bg-green-500 dark:bg-green-600 text-white shadow-lg shadow-green-500/30'
: index === stepIndex
? 'bg-primary-500 text-white ring-4 ring-primary-100 shadow-lg shadow-primary-500/30'
: 'bg-slate-100 text-slate-400'
? 'bg-primary-500 dark:bg-primary-600 text-white ring-4 ring-primary-100 dark:ring-primary-900/50 shadow-lg shadow-primary-500/30'
: 'bg-slate-100 dark:bg-slate-700 text-slate-400 dark:text-slate-500'
}`}
>
{index < stepIndex ? <Check className="w-5 h-5" /> : index + 1}
</div>
<p className={`mt-2 text-xs font-medium hidden sm:block transition-colors ${
index <= stepIndex ? 'text-slate-900' : 'text-slate-400'
index <= stepIndex ? 'text-slate-900 dark:text-slate-100' : 'text-slate-400 dark:text-slate-500'
}`}>
{step.title}
</p>
</div>
{index < steps.length - 1 && (
<div className={`w-16 sm:w-24 h-1 mx-2 rounded-full transition-colors duration-500 ${
index < stepIndex ? 'bg-green-500' : 'bg-slate-200'
index < stepIndex ? 'bg-green-500 dark:bg-green-600' : 'bg-slate-200 dark:bg-slate-700'
}`} />
)}
</div>
@@ -376,7 +376,7 @@ export function Setup() {
</div>
{error && (
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-xl flex items-center gap-3 text-red-700">
<div className="mb-6 p-4 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-xl flex items-center gap-3 text-red-700 dark:text-red-300">
<AlertCircle className="w-5 h-5 flex-shrink-0" />
<p>{error}</p>
</div>
@@ -388,8 +388,8 @@ export function Setup() {
<div className="w-24 h-24 mx-auto mb-6 rounded-2xl bg-gradient-to-br from-primary-100 to-primary-200 flex items-center justify-center shadow-xl shadow-primary-500/10">
<Link2 className="w-12 h-12 text-primary-600" />
</div>
<h1 className="text-3xl font-bold text-slate-900 mb-3">Connect your email account</h1>
<p className="text-lg text-slate-600 mb-10 max-w-md mx-auto">
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100 mb-3">Connect your email account</h1>
<p className="text-lg text-slate-600 dark:text-slate-400 mb-10 max-w-md mx-auto">
Choose your email provider. The connection is secure and your data stays private.
</p>
@@ -416,10 +416,10 @@ export function Setup() {
<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-slate-300"></div>
<div className="w-full border-t border-slate-300 dark:border-slate-600"></div>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-4 bg-white text-slate-500">Or connect your inbox</span>
<span className="px-4 bg-white dark:bg-slate-800 text-slate-500 dark:text-slate-400">Or connect your inbox</span>
</div>
</div>
@@ -427,12 +427,12 @@ export function Setup() {
<button
onClick={handleConnectGmail}
disabled={connecting !== null}
className="flex items-center gap-4 p-6 bg-white rounded-2xl border-2 border-slate-200 hover:border-red-300 hover:shadow-xl hover:shadow-red-500/10 transition-all text-left group disabled:opacity-50 disabled:cursor-not-allowed"
className="flex items-center gap-4 p-6 bg-white dark:bg-slate-800 rounded-2xl border-2 border-slate-200 dark:border-slate-700 hover:border-red-300 dark:hover:border-red-600 hover:shadow-xl hover:shadow-red-500/10 transition-all text-left group disabled:opacity-50 disabled:cursor-not-allowed"
>
{connecting === 'gmail' ? (
<Loader2 className="w-12 h-12 animate-spin text-red-500" />
<Loader2 className="w-12 h-12 animate-spin text-red-500 dark:text-red-400" />
) : (
<div className="w-12 h-12 rounded-xl bg-red-50 flex items-center justify-center group-hover:bg-red-100 transition-colors">
<div className="w-12 h-12 rounded-xl bg-red-50 dark:bg-red-900/30 flex items-center justify-center group-hover:bg-red-100 dark:group-hover:bg-red-900/50 transition-colors">
<svg viewBox="0 0 24 24" className="w-7 h-7">
<path fill="#EA4335" d="M5.26 9.71L12 14.04l6.74-4.33-6.74-4.33z"/>
<path fill="#34A853" d="M12 14.04l6.74-4.33v7.65c0 .7-.57 1.26-1.26 1.26H6.52c-.7 0-1.26-.57-1.26-1.26V9.71l6.74 4.33z"/>
@@ -442,37 +442,37 @@ export function Setup() {
</div>
)}
<div className="flex-1">
<p className="font-semibold text-slate-900">Gmail</p>
<p className="text-sm text-slate-500">Google Workspace</p>
<p className="font-semibold text-slate-900 dark:text-slate-100">Gmail</p>
<p className="text-sm text-slate-500 dark:text-slate-400">Google Workspace</p>
</div>
<ChevronRight className="w-5 h-5 text-slate-400 group-hover:text-red-500 group-hover:translate-x-1 transition-all" />
<ChevronRight className="w-5 h-5 text-slate-400 dark:text-slate-500 group-hover:text-red-500 dark:group-hover:text-red-400 group-hover:translate-x-1 transition-all" />
</button>
<button
onClick={handleConnectOutlook}
disabled={connecting !== null}
className="flex items-center gap-4 p-6 bg-white rounded-2xl border-2 border-slate-200 hover:border-blue-300 hover:shadow-xl hover:shadow-blue-500/10 transition-all text-left group disabled:opacity-50 disabled:cursor-not-allowed"
className="flex items-center gap-4 p-6 bg-white dark:bg-slate-800 rounded-2xl border-2 border-slate-200 dark:border-slate-700 hover:border-blue-300 dark:hover:border-blue-600 hover:shadow-xl hover:shadow-blue-500/10 transition-all text-left group disabled:opacity-50 disabled:cursor-not-allowed"
>
{connecting === 'outlook' ? (
<Loader2 className="w-12 h-12 animate-spin text-blue-500" />
<Loader2 className="w-12 h-12 animate-spin text-blue-500 dark:text-blue-400" />
) : (
<div className="w-12 h-12 rounded-xl bg-blue-50 flex items-center justify-center group-hover:bg-blue-100 transition-colors">
<div className="w-12 h-12 rounded-xl bg-blue-50 dark:bg-blue-900/30 flex items-center justify-center group-hover:bg-blue-100 dark:group-hover:bg-blue-900/50 transition-colors">
<svg viewBox="0 0 24 24" className="w-7 h-7">
<path fill="#0078D4" d="M11.5 3v8.5H3V3h8.5zm1 0H21v8.5h-8.5V3zM3 12.5h8.5V21H3v-8.5zm9.5 0H21V21h-8.5v-8.5z"/>
</svg>
</div>
)}
<div className="flex-1">
<p className="font-semibold text-slate-900">Outlook</p>
<p className="text-sm text-slate-500">Microsoft 365</p>
<p className="font-semibold text-slate-900 dark:text-slate-100">Outlook</p>
<p className="text-sm text-slate-500 dark:text-slate-400">Microsoft 365</p>
</div>
<ChevronRight className="w-5 h-5 text-slate-400 group-hover:text-blue-500 group-hover:translate-x-1 transition-all" />
<ChevronRight className="w-5 h-5 text-slate-400 dark:text-slate-500 group-hover:text-blue-500 dark:group-hover:text-blue-400 group-hover:translate-x-1 transition-all" />
</button>
</div>
</div>
<div className="mt-10 p-4 bg-slate-50 rounded-xl max-w-lg mx-auto">
<p className="text-sm text-slate-500">
<div className="mt-10 p-4 bg-slate-50 dark:bg-slate-800/50 rounded-xl max-w-lg mx-auto">
<p className="text-sm text-slate-500 dark:text-slate-400">
🔒 Your data is secure. We don't store email content and only have read access.
</p>
</div>
@@ -485,16 +485,16 @@ export function Setup() {
<div className="w-24 h-24 mx-auto mb-6 rounded-2xl bg-gradient-to-br from-primary-100 to-primary-200 flex items-center justify-center shadow-xl shadow-primary-500/10">
<Settings className="w-12 h-12 text-primary-600" />
</div>
<h1 className="text-3xl font-bold text-slate-900 mb-3">Sorting Settings</h1>
<p className="text-lg text-slate-600 max-w-md mx-auto">
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100 mb-3">Sorting Settings</h1>
<p className="text-lg text-slate-600 dark:text-slate-400 max-w-md mx-auto">
Customize how strictly the AI should sort your emails.
</p>
</div>
<Card className="max-w-lg mx-auto shadow-xl border-0">
<Card className="max-w-lg mx-auto shadow-xl border-0 dark:bg-slate-800 dark:border-slate-700">
<CardContent className="p-8 space-y-8">
<div>
<label className="block text-sm font-semibold text-slate-900 mb-4">Sorting Intensity</label>
<label className="block text-sm font-semibold text-slate-900 dark:text-slate-100 mb-4">Sorting Intensity</label>
<div className="grid grid-cols-3 gap-3">
{[
{ id: 'light', name: 'Light', desc: 'Only obvious distractions', emoji: '🌱' },
@@ -506,30 +506,30 @@ export function Setup() {
onClick={() => setPreferences(p => ({ ...p, sortingStrictness: option.id }))}
className={`p-4 rounded-xl border-2 text-center transition-all ${
preferences.sortingStrictness === option.id
? 'border-primary-500 bg-primary-50 shadow-lg shadow-primary-500/10'
: 'border-slate-200 hover:border-slate-300 bg-white'
? 'border-primary-500 dark:border-primary-400 bg-primary-50 dark:bg-primary-900/30 shadow-lg shadow-primary-500/10'
: 'border-slate-200 dark:border-slate-700 hover:border-slate-300 dark:hover:border-slate-600 bg-white dark:bg-slate-800'
}`}
>
<span className="text-2xl mb-2 block">{option.emoji}</span>
<p className="font-semibold text-slate-900">{option.name}</p>
<p className="text-xs text-slate-500 mt-1">{option.desc}</p>
<p className="font-semibold text-slate-900 dark:text-slate-100">{option.name}</p>
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1">{option.desc}</p>
</button>
))}
</div>
</div>
<div className="flex items-center justify-between p-5 bg-gradient-to-r from-slate-50 to-slate-100 rounded-xl">
<div className="flex items-center justify-between p-5 bg-gradient-to-r from-slate-50 to-slate-100 dark:from-slate-800 dark:to-slate-700 rounded-xl">
<div>
<p className="font-semibold text-slate-900">Historical emails</p>
<p className="text-sm text-slate-500">Analyze and sort last 30 days</p>
<p className="font-semibold text-slate-900 dark:text-slate-100">Historical emails</p>
<p className="text-sm text-slate-500 dark:text-slate-400">Analyze and sort last 30 days</p>
</div>
<button
onClick={() => setPreferences(p => ({ ...p, historicalSync: !p.historicalSync }))}
className={`w-14 h-8 rounded-full transition-all duration-300 ${
preferences.historicalSync ? 'bg-primary-500 shadow-lg shadow-primary-500/30' : 'bg-slate-300'
preferences.historicalSync ? 'bg-primary-500 dark:bg-primary-600 shadow-lg shadow-primary-500/30' : 'bg-slate-300 dark:bg-slate-600'
}`}
>
<div className={`w-6 h-6 bg-white rounded-full shadow-md transition-transform duration-300 ${
<div className={`w-6 h-6 bg-white dark:bg-slate-200 rounded-full shadow-md transition-transform duration-300 ${
preferences.historicalSync ? 'translate-x-7' : 'translate-x-1'
}`} />
</button>
@@ -545,8 +545,8 @@ export function Setup() {
<div className="w-24 h-24 mx-auto mb-6 rounded-2xl bg-gradient-to-br from-primary-100 to-primary-200 flex items-center justify-center shadow-xl shadow-primary-500/10">
<Zap className="w-12 h-12 text-primary-600" />
</div>
<h1 className="text-3xl font-bold text-slate-900 mb-3">Choose your categories</h1>
<p className="text-lg text-slate-600 max-w-md mx-auto">
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100 mb-3">Choose your categories</h1>
<p className="text-lg text-slate-600 dark:text-slate-400 max-w-md mx-auto">
Which categories should your emails be sorted into?
</p>
</div>
@@ -558,21 +558,21 @@ export function Setup() {
onClick={() => toggleCategory(category.id)}
className={`flex items-center gap-4 p-5 rounded-xl border-2 text-left transition-all ${
selectedCategories.includes(category.id)
? 'border-primary-500 bg-primary-50 shadow-lg shadow-primary-500/10'
: 'border-slate-200 bg-white hover:border-slate-300 hover:shadow-md'
? 'border-primary-500 dark:border-primary-400 bg-primary-50 dark:bg-primary-900/30 shadow-lg shadow-primary-500/10'
: 'border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 hover:border-slate-300 dark:hover:border-slate-600 hover:shadow-md'
}`}
>
<div className={`w-12 h-12 rounded-xl ${category.color} flex items-center justify-center text-2xl shadow-lg`}>
{category.icon}
</div>
<div className="flex-1">
<p className="font-semibold text-slate-900">{category.name}</p>
<p className="text-sm text-slate-500">{category.description}</p>
<p className="font-semibold text-slate-900 dark:text-slate-100">{category.name}</p>
<p className="text-sm text-slate-500 dark:text-slate-400">{category.description}</p>
</div>
<div className={`w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all ${
selectedCategories.includes(category.id)
? 'border-primary-500 bg-primary-500'
: 'border-slate-300'
? 'border-primary-500 dark:border-primary-400 bg-primary-500 dark:bg-primary-600'
: 'border-slate-300 dark:border-slate-600'
}`}>
{selectedCategories.includes(category.id) && <Check className="w-4 h-4 text-white" />}
</div>
@@ -580,7 +580,7 @@ export function Setup() {
))}
</div>
<p className="text-center text-sm text-slate-500 mt-6">
<p className="text-center text-sm text-slate-500 dark:text-slate-400 mt-6">
You can change these categories later in settings.
</p>
</div>
@@ -591,20 +591,20 @@ export function Setup() {
<div className="w-28 h-28 mx-auto mb-8 rounded-full bg-gradient-to-br from-green-100 to-green-200 flex items-center justify-center shadow-2xl shadow-green-500/20 animate-pulse">
<Sparkles className="w-14 h-14 text-green-600" />
</div>
<h1 className="text-4xl font-bold text-slate-900 mb-4">All set! 🎉</h1>
<p className="text-xl text-slate-600 mb-10 max-w-md mx-auto">
<h1 className="text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">All set! 🎉</h1>
<p className="text-xl text-slate-600 dark:text-slate-400 mb-10 max-w-md mx-auto">
Your email account is connected. The AI will now start intelligent sorting.
</p>
<div className="inline-flex items-center gap-4 p-5 bg-gradient-to-r from-slate-50 to-slate-100 rounded-2xl mb-10 shadow-lg">
<div className="w-14 h-14 rounded-xl bg-white flex items-center justify-center shadow-md">
<Mail className="w-7 h-7 text-primary-500" />
<div className="inline-flex items-center gap-4 p-5 bg-gradient-to-r from-slate-50 to-slate-100 dark:from-slate-800 dark:to-slate-700 rounded-2xl mb-10 shadow-lg">
<div className="w-14 h-14 rounded-xl bg-white dark:bg-slate-700 flex items-center justify-center shadow-md">
<Mail className="w-7 h-7 text-primary-500 dark:text-primary-400" />
</div>
<div className="text-left">
<p className="font-semibold text-slate-900 text-lg">
<p className="font-semibold text-slate-900 dark:text-slate-100 text-lg">
{connectedProvider === 'gmail' ? 'Gmail' : connectedProvider === 'outlook' ? 'Outlook' : 'Email'} connected
</p>
<p className="text-slate-500">{connectedEmail || user?.email}</p>
<p className="text-slate-500 dark:text-slate-400">{connectedEmail || user?.email}</p>
</div>
<Badge variant="success" className="text-sm px-3 py-1">Active</Badge>
</div>
@@ -628,7 +628,7 @@ export function Setup() {
{currentStep !== 'connect' && currentStep !== 'complete' && (
<div className="flex justify-between max-w-lg mx-auto">
<Button variant="ghost" onClick={handleBack} className="text-slate-600">
<Button variant="ghost" onClick={handleBack} className="text-slate-600 dark:text-slate-400">
<ArrowLeft className="w-5 h-5 mr-2" />
Back
</Button>

View File

@@ -51,26 +51,26 @@ export function VerifyEmail() {
}
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 flex items-center justify-center p-4">
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800 flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* Logo */}
<Link to="/" className="flex items-center justify-center gap-2 mb-8">
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-primary-500 to-primary-700 flex items-center justify-center">
<Mail className="w-5 h-5 text-white" />
</div>
<span className="text-xl font-bold text-slate-900">
Email<span className="text-primary-600">Sorter</span>
<span className="text-xl font-bold text-slate-900 dark:text-slate-100">
Email<span className="text-primary-600 dark:text-primary-400">Sorter</span>
</span>
</Link>
<Card className="shadow-xl border-0">
<Card className="shadow-xl border-0 dark:bg-slate-800 dark:border-slate-700">
<CardHeader className="text-center pb-2">
<CardTitle className="text-2xl">
<CardTitle className="text-2xl dark:text-slate-100">
{status === 'loading' && 'E-Mail wird verifiziert...'}
{status === 'success' && 'E-Mail verifiziert!'}
{status === 'error' && 'Verifizierung fehlgeschlagen'}
</CardTitle>
<CardDescription>
<CardDescription className="dark:text-slate-400">
{status === 'loading' && 'Bitte warte einen Moment.'}
{status === 'success' && 'Deine E-Mail-Adresse wurde erfolgreich bestätigt.'}
{status === 'error' && error}
@@ -79,25 +79,25 @@ export function VerifyEmail() {
<CardContent>
{status === 'loading' && (
<div className="flex flex-col items-center py-12">
<Loader2 className="w-12 h-12 animate-spin text-primary-500 mb-4" />
<p className="text-slate-500">Verifizierung läuft...</p>
<Loader2 className="w-12 h-12 animate-spin text-primary-500 dark:text-primary-400 mb-4" />
<p className="text-slate-500 dark:text-slate-400">Verifizierung läuft...</p>
</div>
)}
{status === 'success' && (
<div className="text-center py-8">
<div className="w-20 h-20 mx-auto mb-6 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-10 h-10 text-green-600" />
<div className="w-20 h-20 mx-auto mb-6 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center">
<CheckCircle className="w-10 h-10 text-green-600 dark:text-green-400" />
</div>
<div className="space-y-4">
<div className="p-4 bg-green-50 border border-green-100 rounded-xl">
<p className="text-green-700 font-medium">
<div className="p-4 bg-green-50 dark:bg-green-900/30 border border-green-100 dark:border-green-800 rounded-xl">
<p className="text-green-700 dark:text-green-300 font-medium">
Dein Account ist jetzt vollständig aktiviert!
</p>
</div>
<p className="text-slate-600">
<p className="text-slate-600 dark:text-slate-400">
Du kannst jetzt alle Features von EmailSorter nutzen.
</p>
@@ -110,18 +110,18 @@ export function VerifyEmail() {
{status === 'error' && (
<div className="text-center py-8">
<div className="w-20 h-20 mx-auto mb-6 rounded-full bg-red-100 flex items-center justify-center">
<XCircle className="w-10 h-10 text-red-600" />
<div className="w-20 h-20 mx-auto mb-6 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center">
<XCircle className="w-10 h-10 text-red-600 dark:text-red-400" />
</div>
<div className="space-y-4">
<div className="p-4 bg-red-50 border border-red-100 rounded-xl">
<p className="text-red-700">
<div className="p-4 bg-red-50 dark:bg-red-900/30 border border-red-100 dark:border-red-800 rounded-xl">
<p className="text-red-700 dark:text-red-300">
{error || 'Der Verifizierungslink ist ungültig oder abgelaufen.'}
</p>
</div>
<p className="text-slate-600 text-sm">
<p className="text-slate-600 dark:text-slate-400 text-sm">
Falls dein Link abgelaufen ist, kannst du eine neue Verifizierungs-E-Mail anfordern.
</p>
@@ -142,9 +142,9 @@ export function VerifyEmail() {
</Card>
{/* Help text */}
<p className="text-center text-sm text-slate-500 mt-6">
<p className="text-center text-sm text-slate-500 dark:text-slate-400 mt-6">
Probleme? Kontaktiere uns unter{' '}
<a href="mailto:support@emailsorter.de" className="text-primary-600 hover:underline">
<a href="mailto:support@emailsorter.de" className="text-primary-600 dark:text-primary-400 hover:underline">
support@emailsorter.de
</a>
</p>