+
+
-
Handel
-
Von der einfachen Handelskasse bis hin zur vollwertigen ERP. Wir können es.
+
Handel & ERP
+
Erweiterungen für Handelskassen, Bestandsführung und vollwertige Warenwirtschaftssysteme (ERP).
-
-
+
+ {/* Modul 2 */}
+
+
+
-
Gastro
-
Egal ob mobiles Ordern, einer Küchen-Anzeige oder einen Pick-Up-Bord. Wir können es.
+
Gastronomie
+
Lizenzen für mobiles Bestellen (Orderman), digitale Küchen-Monitore und interaktive Abhol-Boards.
-
-
-
+
+ {/* Modul 3 */}
+
+
+
-
Hybrid Systeme
-
Sie benötigen eine Lösung aus beiden Welten? Sprechen Sie uns an.
+
Hybride Systeme
+
Das beste aus beiden Welten. Handel mit Gastronomie und umgekehrt.
+
+
+
+
+
+
+ {/* Kurze Info-Sektion für Partner / Händler */}
+
+
+
Wie funktioniert die Bereitstellung?
+
+
+
+
1. Lizenz wählen: Gewünschtes POS-Modul im Shop selektieren.
+
+
+
+
2. Kunde zuweisen: Lizenz direkt einem Kunden-Account zuordnen.
+
+
+
+
3. Live gehen: Lizenz-Key (`.key`) wird sofort serverseitig aktiviert.
-
)
-}
+}
\ No newline at end of file
diff --git a/shop/components/Navbar.tsx b/shop/components/Navbar.tsx
new file mode 100644
index 0000000..938adae
--- /dev/null
+++ b/shop/components/Navbar.tsx
@@ -0,0 +1,49 @@
+import { createServerClient } from "@supabase/ssr";
+import { cookies } from "next/headers";
+import { NavbarClient } from "@/components/NavbarClient";
+
+export async function Navbar() {
+ const cookieStore = await cookies();
+
+ const supabaseUrl = process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL;
+ const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY || process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
+
+ if (!supabaseUrl || !supabaseAnonKey) {
+ // Falls keine Env-Vars da sind, leeren User an Client übergeben
+ return
;
+ }
+
+ const supabase = createServerClient(
+ supabaseUrl,
+ supabaseAnonKey,
+ {
+ cookies: {
+ getAll() {
+ return cookieStore.getAll();
+ },
+ setAll(cookiesToSet) {
+ try {
+ cookiesToSet.forEach(({ name, value, options }) =>
+ cookieStore.set(name, value, options),
+ );
+ } catch {
+ // Kann in Server Components ignoriert werden, da dort keine Cookies gesetzt werden können
+ }
+ },
+ },
+ cookieOptions: {
+ name: "webshop-auth-token",
+ },
+ },
+ );
+
+ let user = null;
+ try {
+ const { data } = await supabase.auth.getUser();
+ user = data.user;
+ } catch (error) {
+ console.error("Fehler beim Abrufen des Users in Navbar:", error);
+ }
+
+ return
;
+}
diff --git a/shop/components/NavbarClient.tsx b/shop/components/NavbarClient.tsx
new file mode 100644
index 0000000..1b42b9a
--- /dev/null
+++ b/shop/components/NavbarClient.tsx
@@ -0,0 +1,217 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import Link from "next/link";
+import { useRouter } from "next/navigation";
+import { createBrowserClient } from "@supabase/ssr";
+import { type User } from "@supabase/supabase-js";
+import { Rocket, Menu, X, User as UserIcon, LogOut } from "lucide-react";
+import { Button } from "@/components/ui/button";
+
+interface NavbarClientProps {
+ user: User | null;
+}
+
+export function NavbarClient({ user }: NavbarClientProps) {
+ const router = useRouter();
+ const [currentUser, setCurrentUser] = useState
(user);
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
+ const [open, setOpen] = useState(false);
+
+ // Supabase URL & Anon Key auslesen (für Browser-Client)
+ const supabaseUrl = process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL;
+ const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY || process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
+
+ // Supabase URL Auflösung inline
+ let resolvedUrl = supabaseUrl;
+ if (resolvedUrl && typeof window !== "undefined") {
+ try {
+ const parsed = new URL(resolvedUrl);
+ if (parsed.hostname === "supabase-kong" || parsed.hostname === "kong") {
+ parsed.hostname = window.location.hostname;
+ resolvedUrl = parsed.toString().replace(/\/$/, "");
+ }
+ } catch {
+ resolvedUrl = resolvedUrl
+ .replace("//supabase-kong", `//${window.location.hostname}`)
+ .replace("//kong", `//${window.location.hostname}`);
+ }
+ }
+
+ // Browser Client inline erstellen
+ const supabase = createBrowserClient(
+ resolvedUrl!,
+ supabaseAnonKey!,
+ {
+ cookieOptions: {
+ name: "webshop-auth-token",
+ },
+ }
+ );
+
+ // Auf Auth-Statusänderungen reagieren
+ useEffect(() => {
+ const {
+ data: { subscription },
+ } = supabase.auth.onAuthStateChange((event, session) => {
+ setCurrentUser(session?.user ?? null);
+ });
+
+ return () => {
+ subscription.unsubscribe();
+ };
+ }, [supabase]);
+
+ const handleSignOut = async () => {
+ await supabase.auth.signOut();
+ setCurrentUser(null);
+ setIsMobileMenuOpen(false);
+ router.refresh();
+ router.push("/");
+ };
+
+ return (
+ <>
+
+
+ CASPOS Store
+
+ Demo
+
+
+
+ {/* Desktop Navigation */}
+
+
+ {/* Mobile Hamburger Trigger */}
+
+
+
+ {/* Mobile Menu Panel */}
+ {isMobileMenuOpen && (
+
+
setIsMobileMenuOpen(false)}
+ >
+ Bestellen
+
+
setIsMobileMenuOpen(false)}
+ >
+ Wiki
+
+
setIsMobileMenuOpen(false)}
+ >
+ Support
+
+
+ {currentUser && (
+ <>
+
+
Mein Account ({currentUser.email})
+
setIsMobileMenuOpen(false)}
+ >
+ Account Kunden
+
+ >
+ )}
+
+
+
+ {currentUser ? (
+
+ ) : (
+
+ )}
+
+ )}
+ >
+ );
+}