diff --git a/frontend/src/app/admin/page.tsx b/frontend/src/app/admin/page.tsx index 9bdd317..22de696 100644 --- a/frontend/src/app/admin/page.tsx +++ b/frontend/src/app/admin/page.tsx @@ -329,9 +329,9 @@ export default function AdminPage() { Total Requests -
{dashboard.rate_limits.total_requests.toLocaleString()}
+
{(dashboard.rate_limits?.total_requests ?? 0).toLocaleString()}
- {dashboard.rate_limits.active_clients} active clients + {dashboard.rate_limits?.active_clients ?? 0} active clients
@@ -343,9 +343,9 @@ export default function AdminPage() { Translations -
{dashboard.translations.total.toLocaleString()}
+
{(dashboard.translations?.total ?? 0).toLocaleString()}
- {dashboard.translations.success_rate}% success rate + {dashboard.translations?.success_rate ?? 0}% success rate
@@ -357,9 +357,9 @@ export default function AdminPage() { Memory Usage -
{dashboard.system.memory.system_percent}%
+
{dashboard.system?.memory?.system_percent ?? 0}%
- {dashboard.system.memory.system_available_gb.toFixed(1)} GB available + {(dashboard.system?.memory?.system_available_gb ?? 0).toFixed(1)} GB available
@@ -371,9 +371,9 @@ export default function AdminPage() { Tracked Files -
{dashboard.cleanup.tracked_files_count}
+
{dashboard.cleanup?.tracked_files_count ?? 0}
- {dashboard.system.disk.total_size_mb.toFixed(1)} MB total + {(dashboard.system?.disk?.total_size_mb ?? 0).toFixed(1)} MB total
@@ -389,19 +389,19 @@ export default function AdminPage() {
Requests per minute - {dashboard.rate_limits.config.requests_per_minute} + {dashboard.rate_limits?.config?.requests_per_minute ?? 0}
Translations per minute - {dashboard.rate_limits.config.translations_per_minute} + {dashboard.rate_limits?.config?.translations_per_minute ?? 0}
Max file size - {dashboard.config.max_file_size_mb} MB + {dashboard.config?.max_file_size_mb ?? 0} MB
Translation service - {dashboard.config.translation_service} + {dashboard.config?.translation_service ?? 'N/A'}
@@ -423,21 +423,21 @@ export default function AdminPage() {
Service status - - {dashboard.cleanup.is_running ? "Running" : "Stopped"} + + {dashboard.cleanup?.is_running ? "Running" : "Stopped"}
Files cleaned - {dashboard.cleanup.files_cleaned_total} + {dashboard.cleanup?.files_cleaned_total ?? 0}
Space freed - {dashboard.cleanup.bytes_freed_total_mb.toFixed(2)} MB + {(dashboard.cleanup?.bytes_freed_total_mb ?? 0).toFixed(2)} MB
Cleanup runs - {dashboard.cleanup.cleanup_runs} + {dashboard.cleanup?.cleanup_runs ?? 0}
diff --git a/frontend/src/app/auth/login/page.tsx b/frontend/src/app/auth/login/page.tsx index 72696ac..d82239b 100644 --- a/frontend/src/app/auth/login/page.tsx +++ b/frontend/src/app/auth/login/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, Suspense } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import Link from "next/link"; import { Eye, EyeOff, Mail, Lock, ArrowRight, Loader2 } from "lucide-react"; @@ -8,7 +8,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -export default function LoginPage() { +function LoginForm() { const router = useRouter(); const searchParams = useSearchParams(); const redirect = searchParams.get("redirect") || "/"; @@ -51,6 +51,122 @@ export default function LoginPage() { } }; + return ( + <> + {/* Card */} +
+
+

Welcome back

+

Sign in to continue translating

+
+ + {error && ( +
+ {error} +
+ )} + +
+
+ +
+ + setEmail(e.target.value)} + required + className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" + /> +
+
+ +
+
+ + + Forgot password? + +
+
+ + setPassword(e.target.value)} + required + className="pl-10 pr-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" + /> + +
+
+ + +
+ +
+ Don't have an account?{" "} + + Sign up for free + +
+
+ + {/* Features reminder */} +
+

Start with our free plan:

+
+ {["5 docs/day", "10 pages/doc", "Free forever"].map((feature) => ( + + {feature} + + ))} +
+
+ + ); +} + +function LoadingFallback() { + return ( +
+
+ +
+
+ ); +} + +export default function LoginPage() { return (
@@ -64,105 +180,9 @@ export default function LoginPage() {
- {/* Card */} -
-
-

Welcome back

-

Sign in to continue translating

-
- - {error && ( -
- {error} -
- )} - -
-
- -
- - setEmail(e.target.value)} - required - className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" - /> -
-
- -
-
- - - Forgot password? - -
-
- - setPassword(e.target.value)} - required - className="pl-10 pr-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" - /> - -
-
- - -
- -
- Don't have an account?{" "} - - Sign up for free - -
-
- - {/* Features reminder */} -
-

Start with our free plan:

-
- {["3 docs/day", "10 pages/doc", "Ollama support"].map((feature) => ( - - {feature} - - ))} -
-
+ }> + +
); diff --git a/frontend/src/app/auth/register/page.tsx b/frontend/src/app/auth/register/page.tsx index 697adb6..c4d4ea3 100644 --- a/frontend/src/app/auth/register/page.tsx +++ b/frontend/src/app/auth/register/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, Suspense } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import Link from "next/link"; import { Eye, EyeOff, Mail, Lock, User, ArrowRight, Loader2 } from "lucide-react"; @@ -8,7 +8,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -export default function RegisterPage() { +function RegisterForm() { const router = useRouter(); const searchParams = useSearchParams(); const redirect = searchParams.get("redirect") || "/"; @@ -64,6 +64,146 @@ export default function RegisterPage() { } }; + return ( + <> + {/* Card */} +
+
+

Create an account

+

Start translating documents for free

+
+ + {error && ( +
+ {error} +
+ )} + +
+
+ +
+ + setName(e.target.value)} + required + className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" + /> +
+
+ +
+ +
+ + setEmail(e.target.value)} + required + className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" + /> +
+
+ +
+ +
+ + setPassword(e.target.value)} + required + minLength={8} + className="pl-10 pr-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" + /> + +
+
+ +
+ +
+ + setConfirmPassword(e.target.value)} + required + className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" + /> +
+
+ + +
+ +
+ Already have an account?{" "} + + Sign in + +
+ +
+ By creating an account, you agree to our{" "} + + Terms of Service + {" "} + and{" "} + + Privacy Policy + +
+
+ + ); +} + +function LoadingFallback() { + return ( +
+
+ +
+
+ ); +} + +export default function RegisterPage() { return (
@@ -77,129 +217,9 @@ export default function RegisterPage() {
- {/* Card */} -
-
-

Create an account

-

Start translating documents for free

-
- - {error && ( -
- {error} -
- )} - -
-
- -
- - setName(e.target.value)} - required - className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" - /> -
-
- -
- -
- - setEmail(e.target.value)} - required - className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" - /> -
-
- -
- -
- - setPassword(e.target.value)} - required - minLength={8} - className="pl-10 pr-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" - /> - -
-
- -
- -
- - setConfirmPassword(e.target.value)} - required - className="pl-10 bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" - /> -
-
- - -
- -
- Already have an account?{" "} - - Sign in - -
- -
- By creating an account, you agree to our{" "} - - Terms of Service - {" "} - and{" "} - - Privacy Policy - -
-
+ }> + +
); diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 835a5a9..5806703 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1,30 +1,15 @@ "use client"; import { FileUploader } from "@/components/file-uploader"; -import { useTranslationStore } from "@/lib/store"; -import { Badge } from "@/components/ui/badge"; -import { Settings } from "lucide-react"; -import Link from "next/link"; import { LandingHero, FeaturesSection, PricingPreview, SelfHostCTA } from "@/components/landing-sections"; +import Link from "next/link"; export default function Home() { - const { settings } = useTranslationStore(); - - const providerNames: Record = { - openrouter: "OpenRouter", - google: "Google Translate", - ollama: "Ollama", - deepl: "DeepL", - libre: "LibreTranslate", - webllm: "WebLLM", - openai: "OpenAI", - }; - return (
{/* Hero Section */} @@ -33,28 +18,11 @@ export default function Home() { {/* Upload Section */}
-
-
-

Translate Your Document

-

- Upload and translate Excel, Word, and PowerPoint files while preserving all formatting. -

-
- - {/* Current Configuration Badge */} - - -
- - {providerNames[settings.defaultProvider]} - - {settings.defaultProvider === "ollama" && settings.ollamaModel && ( - - {settings.ollamaModel} - - )} -
- +
+

Translate Your Document

+

+ Upload and translate Excel, Word, and PowerPoint files while preserving all formatting. +

@@ -81,7 +49,6 @@ export default function Home() {
Pricing - Self-Host Terms Privacy
diff --git a/frontend/src/components/file-uploader.tsx b/frontend/src/components/file-uploader.tsx index eb10242..6ac3081 100644 --- a/frontend/src/components/file-uploader.tsx +++ b/frontend/src/components/file-uploader.tsx @@ -323,104 +323,34 @@ export function FileUploader() { Translation Options - Configure your translation preferences + Select your target language and start translating -
- {/* Target Language */} -
- - -
- - {/* Provider */} -
- - - {/* Warning if API key not configured */} - {provider === "openai" && !settings.openaiApiKey && ( -

- ⚠️ OpenAI API key not configured. Go to Settings → Translation Services -

- )} - {provider === "deepl" && !settings.deeplApiKey && ( -

- ⚠️ DeepL API key not configured. Go to Settings → Translation Services -

- )} - {provider === "webllm" && !webllm.isLoaded && ( -

- ⚠️ WebLLM model not loaded. Go to Settings → Translation Services to load a model -

- )} - {provider === "webllm" && webllm.isLoaded && ( -

- - Model ready: {webllm.currentModel} -

- )} - {provider === "webllm" && !webllm.isWebGPUSupported() && ( -

- - WebGPU not supported in this browser -

- )} -
+ {/* Target Language */} +
+ +
- {/* Image Translation Toggle */} - {(provider === "ollama" || provider === "openai") && ( -
-
- -

- Extract and translate text from embedded images using vision model -

-
- -
- )} - {/* Translate Button */} - -
-
-
- ); + return null; // Removed for commercial version } diff --git a/frontend/src/components/sidebar.tsx b/frontend/src/components/sidebar.tsx index 4fc4f66..99939f6 100644 --- a/frontend/src/components/sidebar.tsx +++ b/frontend/src/components/sidebar.tsx @@ -5,15 +5,11 @@ import { usePathname } from "next/navigation"; import { useState, useEffect, useCallback, memo } from "react"; import { cn } from "@/lib/utils"; import { - Settings, - Cloud, - BookText, Upload, LayoutDashboard, LogIn, Crown, LogOut, - Server, } from "lucide-react"; import { Tooltip, @@ -37,24 +33,6 @@ const navigation = [ icon: Upload, description: "Translate documents", }, - { - name: "Translation Services", - href: "/settings/services", - icon: Cloud, - description: "Configure translation providers", - }, - { - name: "Context & Glossary", - href: "/settings/context", - icon: BookText, - description: "System prompts and glossary", - }, - { - name: "General Settings", - href: "/settings", - icon: Settings, - description: "Configure general settings", - }, ]; const planColors: Record = { @@ -230,29 +208,6 @@ export function Sidebar() { )}
)} - - {/* Self-Host Option */} -
- - - - - Self-Host (Free) - - - -

Run your own Ollama for unlimited free translations

-
-
-
{/* User section at bottom */}