diff --git a/src/App.tsx b/src/App.tsx index 42cdfac..c3eb6f4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,6 +7,7 @@ import Index from "./pages/Index"; import NotFound from "./pages/NotFound"; import ResetPassword from "./pages/ResetPassword"; import Profile from "./pages/Profile"; +import Account from "./pages/Account"; import { useCartSync } from "./hooks/useCartSync"; const queryClient = new QueryClient(); @@ -20,6 +21,7 @@ function AppContent() { } /> } /> } /> + } /> {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */} } /> diff --git a/src/components/AbonnemangForm.tsx b/src/components/AbonnemangForm.tsx index 999076f..257dc54 100644 --- a/src/components/AbonnemangForm.tsx +++ b/src/components/AbonnemangForm.tsx @@ -1,5 +1,7 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import { z } from "zod"; +import { useAuth } from "@/hooks/useAuth"; +import { supabase } from "@/integrations/supabase/client"; const formSchema = z.object({ företag: z.string().trim().min(1, "Fyll i företagsnamn").max(100), @@ -19,6 +21,7 @@ interface AbonnemangFormProps { } const AbonnemangForm = ({ selectedPlan, onClose }: AbonnemangFormProps) => { + const { user } = useAuth(); const [formData, setFormData] = useState({ företag: "", kontaktperson: "", @@ -34,6 +37,37 @@ const AbonnemangForm = ({ selectedPlan, onClose }: AbonnemangFormProps) => { const [submitted, setSubmitted] = useState(false); const [errors, setErrors] = useState>({}); + // Pre-fill form with user's profile data if logged in + useEffect(() => { + const fetchProfileData = async () => { + if (user) { + const { data } = await supabase + .from("profiles") + .select("display_name, phone, address") + .eq("user_id", user.id) + .maybeSingle(); + + if (data) { + setFormData((prev) => ({ + ...prev, + kontaktperson: data.display_name || prev.kontaktperson, + telefon: data.phone || prev.telefon, + epost: user.email || prev.epost, + // Parse address if it exists (format: "gatuadress, postnummer ort") + adress: data.address?.split(",")[0]?.trim() || prev.adress, + })); + } else { + // At least fill in email + setFormData((prev) => ({ + ...prev, + epost: user.email || prev.epost, + })); + } + } + }; + fetchProfileData(); + }, [user]); + const handleChange = ( e: React.ChangeEvent ) => { @@ -45,6 +79,31 @@ const AbonnemangForm = ({ selectedPlan, onClose }: AbonnemangFormProps) => { } }; + const saveAddressToProfile = async () => { + if (!user) return; + + // Combine address fields into one string + const fullAddress = [ + formData.adress, + formData.postnummer && formData.stad + ? `${formData.postnummer} ${formData.stad}` + : formData.postnummer || formData.stad, + ] + .filter(Boolean) + .join(", "); + + if (fullAddress) { + await supabase + .from("profiles") + .update({ + address: fullAddress, + phone: formData.telefon || null, + display_name: formData.kontaktperson || null, + }) + .eq("user_id", user.id); + } + }; + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setErrors({}); @@ -61,6 +120,9 @@ const AbonnemangForm = ({ selectedPlan, onClose }: AbonnemangFormProps) => { return; } + // Save address to profile if user is logged in + await saveAddressToProfile(); + // For now, just show success - backend integration can be added later setSubmitted(true); }; diff --git a/src/components/AccountMenu.tsx b/src/components/AccountMenu.tsx index b8ab540..60e4277 100644 --- a/src/components/AccountMenu.tsx +++ b/src/components/AccountMenu.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; import { useNavigate } from "react-router-dom"; -import { LogOut, User } from "lucide-react"; import { DropdownMenu, DropdownMenuContent, @@ -12,7 +11,7 @@ import { useAuth } from "@/hooks/useAuth"; import AuthDialog from "./AuthDialog"; const AccountMenu = () => { - const { user, loading, signOut } = useAuth(); + const { user, loading } = useAuth(); const [authDialogOpen, setAuthDialogOpen] = useState(false); const [authMode, setAuthMode] = useState<"login" | "signup">("login"); const navigate = useNavigate(); @@ -22,14 +21,25 @@ const AccountMenu = () => { setAuthDialogOpen(true); }; - const handleSignOut = async () => { - await signOut(); - }; - if (loading) { return null; } + // If user is logged in, navigate directly to account page + if (user) { + return ( + + ); + } + + // If not logged in, show dropdown with login/signup options return ( <> @@ -46,44 +56,20 @@ const AccountMenu = () => { align="end" className="bg-background border border-border shadow-lg z-50 min-w-[160px]" > - {user ? ( - <> - - {user.email} - - navigate("/profile")} - className="cursor-pointer flex items-center gap-2 hover:!bg-[rgba(220,38,38,0.3)] focus:!bg-[rgba(220,38,38,0.3)] hover:!text-black focus:!text-black" - > - - Min profil - - - - Logga ut - - - ) : ( - <> -
- -
- handleOpenAuth("login")} - className="cursor-pointer hover:!bg-[rgba(220,38,38,0.3)] focus:!bg-[rgba(220,38,38,0.3)] hover:!text-black focus:!text-black" - > - Logga in - - - )} +
+ +
+ handleOpenAuth("login")} + className="cursor-pointer hover:!bg-[rgba(220,38,38,0.3)] focus:!bg-[rgba(220,38,38,0.3)] hover:!text-black focus:!text-black" + > + Logga in +
diff --git a/src/pages/Account.tsx b/src/pages/Account.tsx new file mode 100644 index 0000000..a936aff --- /dev/null +++ b/src/pages/Account.tsx @@ -0,0 +1,241 @@ +import { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import { z } from "zod"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import { useAuth } from "@/hooks/useAuth"; +import { useToast } from "@/hooks/use-toast"; +import { supabase } from "@/integrations/supabase/client"; +import Header from "@/components/Header"; +import { LogOut, Save } from "lucide-react"; + +const profileSchema = z.object({ + display_name: z.string().trim().max(100, { message: "Namn får max vara 100 tecken" }).optional(), + phone: z.string().trim().max(20, { message: "Telefonnummer får max vara 20 tecken" }).optional(), + address: z.string().trim().max(500, { message: "Adress får max vara 500 tecken" }).optional(), +}); + +interface ProfileData { + display_name: string; + phone: string; + address: string; +} + +const Account = () => { + const [profile, setProfile] = useState({ + display_name: "", + phone: "", + address: "", + }); + const [isLoading, setIsLoading] = useState(true); + const [isSaving, setIsSaving] = useState(false); + const { user, loading: authLoading, signOut } = useAuth(); + const { toast } = useToast(); + const navigate = useNavigate(); + + useEffect(() => { + if (!authLoading && !user) { + navigate("/"); + return; + } + + if (user) { + fetchProfile(); + } + }, [user, authLoading, navigate]); + + const fetchProfile = async () => { + try { + const { data, error } = await supabase + .from("profiles") + .select("display_name, phone, address") + .eq("user_id", user!.id) + .maybeSingle(); + + if (error) { + console.error("Error fetching profile:", error); + toast({ + title: "Kunde inte hämta profil", + description: error.message, + variant: "destructive", + }); + } else if (data) { + setProfile({ + display_name: data.display_name || "", + phone: data.phone || "", + address: data.address || "", + }); + } + } finally { + setIsLoading(false); + } + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + const validation = profileSchema.safeParse(profile); + if (!validation.success) { + toast({ + title: "Fel", + description: validation.error.errors[0].message, + variant: "destructive", + }); + return; + } + + setIsSaving(true); + + try { + const { error } = await supabase + .from("profiles") + .update({ + display_name: profile.display_name || null, + phone: profile.phone || null, + address: profile.address || null, + }) + .eq("user_id", user!.id); + + if (error) { + toast({ + title: "Kunde inte spara profil", + description: error.message, + variant: "destructive", + }); + } else { + toast({ + title: "Profil sparad!", + description: "Dina uppgifter har uppdaterats.", + }); + } + } finally { + setIsSaving(false); + } + }; + + const handleSignOut = async () => { + await signOut(); + navigate("/"); + }; + + if (authLoading || isLoading) { + return ( +
+
+
+

Laddar...

+
+
+ ); + } + + return ( +
+
+
+
+ {/* Header */} +
+

+ Mitt konto +

+

{user?.email}

+
+ + {/* Profile Card */} +
+

Mina uppgifter

+ +
+
+ + + setProfile({ ...profile, display_name: e.target.value }) + } + placeholder="Ditt namn" + /> +
+ +
+ + + setProfile({ ...profile, phone: e.target.value }) + } + placeholder="070-123 45 67" + /> +
+ +
+ +