Autosave: 20260408-230340

This commit is contained in:
Flatlogic Bot 2026-04-08 23:03:40 +00:00
parent 67930e0c1a
commit ec7d0e496c
6 changed files with 66 additions and 14 deletions

View File

@ -6,15 +6,17 @@ import { useState } from "react"
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation"
import Link from "next/link" import Link from "next/link"
import { createClient } from "@/lib/supabase/client" import { createClient } from "@/lib/supabase/client"
import { Film, Eye, Loader2 } from "lucide-react" import { Film, Eye, Loader2, Mail } from "lucide-react"
import { useLanguage } from "@/contexts/LanguageContext" import { useLanguage } from "@/contexts/LanguageContext"
import { LanguageToggle } from "@/components/language-toggle" import { LanguageToggle } from "@/components/language-toggle"
import { toast } from "sonner"
export default function LoginPage() { export default function LoginPage() {
const [email, setEmail] = useState("") const [email, setEmail] = useState("")
const [password, setPassword] = useState("") const [password, setPassword] = useState("")
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [resetLoading, setResetLoading] = useState(false)
const router = useRouter() const router = useRouter()
const { t } = useLanguage() const { t } = useLanguage()
@ -22,6 +24,8 @@ export default function LoginPage() {
e.preventDefault() e.preventDefault()
setLoading(true) setLoading(true)
setError(null) setError(null)
console.log("Attempting login for:", email);
const supabase = createClient() const supabase = createClient()
const { error } = await supabase.auth.signInWithPassword({ const { error } = await supabase.auth.signInWithPassword({
@ -30,7 +34,8 @@ export default function LoginPage() {
}) })
if (error) { if (error) {
setError(t("auth.invalidCredentials")) console.error("Login error:", error);
setError(error.message)
setLoading(false) setLoading(false)
return return
} }
@ -39,6 +44,29 @@ export default function LoginPage() {
router.refresh() router.refresh()
} }
async function handleResetPassword() {
if (!email) {
setError("Bitte gib deine E-Mail-Adresse oben ein.")
return
}
setResetLoading(true)
setError(null)
const supabase = createClient()
const { error } = await supabase.auth.resetPasswordForEmail(email, {
redirectTo: `${window.location.origin}/auth/callback?next=/auth/update-password`,
})
if (error) {
setError(error.message)
setResetLoading(false)
} else {
toast.success("E-Mail zum Zurücksetzen des Passworts wurde gesendet.")
setResetLoading(false)
}
}
return ( return (
<main className="flex min-h-dvh flex-col items-center justify-center px-6"> <main className="flex min-h-dvh flex-col items-center justify-center px-6">
<div className="w-full max-w-sm"> <div className="w-full max-w-sm">
@ -108,6 +136,19 @@ export default function LoginPage() {
</button> </button>
</form> </form>
<button
onClick={handleResetPassword}
disabled={resetLoading}
className="mt-4 flex w-full items-center justify-center gap-2 text-sm text-muted-foreground hover:text-primary transition-colors disabled:opacity-50"
>
{resetLoading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Mail className="h-4 w-4" />
)}
Passwort vergessen?
</button>
<p className="mt-6 text-center text-sm text-muted-foreground"> <p className="mt-6 text-center text-sm text-muted-foreground">
{t("auth.dontHaveAccount")}{" "} {t("auth.dontHaveAccount")}{" "}
<Link href="/auth/sign-up" className="font-medium text-primary hover:underline"> <Link href="/auth/sign-up" className="font-medium text-primary hover:underline">

View File

@ -1,8 +1,15 @@
import { createBrowserClient } from '@supabase/ssr' import { createBrowserClient } from '@supabase/ssr'
export function createClient() { export function createClient() {
const url = process.env.NEXT_PUBLIC_SUPABASE_URL || "https://ekbpexbhuochrplzorce.supabase.co";
const key = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "sb_publishable__UII_iKx3pgvLQvc1xrN1w_qnwP6JOv" || process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY;
if (!url || !key) {
console.error("Supabase config missing!", { url: !!url, key: !!key });
}
return createBrowserClient( return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!, url!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, key!,
) )
} }

View File

@ -7,8 +7,8 @@ export async function updateSession(request: NextRequest) {
}) })
const supabase = createServerClient( const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_URL || "https://ekbpexbhuochrplzorce.supabase.co"!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "sb_publishable__UII_iKx3pgvLQvc1xrN1w_qnwP6JOv" || process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY!,
{ {
cookies: { cookies: {
getAll() { getAll() {

View File

@ -5,8 +5,8 @@ export async function createClient() {
const cookieStore = await cookies() const cookieStore = await cookies()
return createServerClient( return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_URL || "https://ekbpexbhuochrplzorce.supabase.co"!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "sb_publishable__UII_iKx3pgvLQvc1xrN1w_qnwP6JOv" || process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY!,
{ {
cookies: { cookies: {
getAll() { getAll() {

2
next-env.d.ts vendored
View File

@ -1,6 +1,6 @@
/// <reference types="next" /> /// <reference types="next" />
/// <reference types="next/image-types/global" /> /// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts"; import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited // NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@ -39,8 +39,10 @@ self.addEventListener("fetch", (event) => {
(cached) => (cached) =>
cached || cached ||
fetch(event.request).then((response) => { fetch(event.request).then((response) => {
const clone = response.clone() if (response.status === 200 && event.request.method === 'GET') {
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone)) const clone = response.clone()
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone))
}
return response return response
}) })
) )
@ -52,10 +54,12 @@ self.addEventListener("fetch", (event) => {
event.respondWith( event.respondWith(
fetch(event.request) fetch(event.request)
.then((response) => { .then((response) => {
const clone = response.clone() if (response.status === 200 && event.request.method === 'GET') {
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone)) const clone = response.clone()
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone))
}
return response return response
}) })
.catch(() => caches.match(event.request)) .catch(() => caches.match(event.request))
) )
}) })