diff --git a/src/api/auth/logout.tsx b/src/api/auth/logout.tsx new file mode 100644 index 0000000..809a79a --- /dev/null +++ b/src/api/auth/logout.tsx @@ -0,0 +1,7 @@ +import { axios } from "@/lib/axios"; + +export const logOut = async () => { + const response = await axios.post(`/user/logout`, { + }); + return response.data; +}; diff --git a/src/api/auth/updateUser.ts b/src/api/auth/updateUser.ts new file mode 100644 index 0000000..5719d35 --- /dev/null +++ b/src/api/auth/updateUser.ts @@ -0,0 +1,16 @@ +import { axios } from "@/lib/axios"; + +interface UpdateUserPayload { + name?: string; + email?: string; + phone?: string; + phone_country?: string; +} + +export const updateUser = async (payload: UpdateUserPayload) => { + + const response = await axios.post("/user/update", payload, { + }); + + return response.data; +}; diff --git a/src/components/ProductsPage/ProductCard.tsx b/src/components/ProductsPage/ProductCard.tsx index 6d6c403..b0ec462 100644 --- a/src/components/ProductsPage/ProductCard.tsx +++ b/src/components/ProductsPage/ProductCard.tsx @@ -23,6 +23,7 @@ const ProductCard = ({ product }: ProductCardProps) => { const isNew = true; const price = parseInt(product.price); const discount = parseInt(product.discount); + const isAvailable = product.types?.some((type) => type.in_stock); const handleAddToCart = async (e: React.MouseEvent) => { e.preventDefault(); @@ -301,7 +302,7 @@ const handleAddToCart = async (e: React.MouseEvent) => { )} - @@ -313,6 +314,7 @@ const handleAddToCart = async (e: React.MouseEvent) => { > + ))} ) => { > (5) + */} + + {isAvailable ? "متوفر" : "غير متوفر"} diff --git a/src/components/general/header/Header.tsx b/src/components/general/header/Header.tsx index 522b7a4..8746182 100644 --- a/src/components/general/header/Header.tsx +++ b/src/components/general/header/Header.tsx @@ -17,6 +17,7 @@ const Header = () => { const pathname = usePathname(); const user = useAuthStore((state) => state.user); const isSignedIn = !!user; + const [hydrated, setHydrated] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [isScrolled, setIsScrolled] = useState(false); @@ -51,6 +52,10 @@ const Header = () => { setIsMobileMenuOpen(!isMobileMenuOpen); }; + useEffect(() => { + setHydrated(true); + }, []); + return ( <> { whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > - {isSignedIn ? ( - - - - ) : ( - - )} + {hydrated && ( + isSignedIn ? ( + + + + ) : ( + + ) + )} { + const user = useAuthStore((state) => state.user); + const setUser = useAuthStore((state) => state.setUser); + const [formData, setFormData] = useState({ + name: user?.name, + email: user?.email, + phone: user?.phone, + job: "", + }); + + console.log(user) + + useEffect(() => { + if (user) { + setFormData({ + name: user.name || "", + email: user.email || "", + phone: user.phone || "", + job: user.job || "" + }); + } + }, [user]); + +const handleUpdate = async () => { + try { + const updatedUser = await updateUser({ + name: formData.name, + phone: formData.phone, + phone_country: "EG", + }); + + setUser(updatedUser.user); + + toast.success("تم تحديث البيانات بنجاح"); + } catch (error: any) { + toast.error( + error?.response?.data?.message || "حدث خطأ أثناء تحديث البيانات" + ); + console.error("Update failed:", error); + } +}; + + return (
@@ -18,6 +64,8 @@ const ProfileDetails = () => { id="name" placeholder="وليد السيد" className="w-full h-16 border border-[#9C9C9C] rounded-[12px] px-4" + value={formData.name} + onChange={(e) => setFormData({ ...formData, name: e.target.value })} />
@@ -34,6 +82,8 @@ const ProfileDetails = () => { id="tel" placeholder="123 4434 543" className="lg:w-[358px] w-full h-16 border border-[#9C9C9C] rounded-[12px] px-4" + value={formData.phone} + onChange={(e) => setFormData({ ...formData, phone: e.target.value })} />
@@ -49,6 +99,8 @@ const ProfileDetails = () => { id="email" placeholder="Walid Elsayed22@Gmail.com" className="lg:w-[358px] w-full h-16 border border-[#9C9C9C] rounded-[12px] px-4" + value={formData.email} + readOnly />

لا يمكن تغيير البريد الإلكتروني المستخدم لتسجيل الدخول @@ -67,12 +119,17 @@ const ProfileDetails = () => { id="job" placeholder="UI UX Designer" className="lg:w-[358px] w-full h-16 border border-[#9C9C9C] rounded-[12px] px-4" + value={formData.job} + onChange={(e) => setFormData({ ...formData, job: e.target.value })} />

-
- حفظ التعديلات -
+
); }; diff --git a/src/components/profile/ProfileSidebar.tsx b/src/components/profile/ProfileSidebar.tsx index 28b5780..8e96bc1 100644 --- a/src/components/profile/ProfileSidebar.tsx +++ b/src/components/profile/ProfileSidebar.tsx @@ -1,8 +1,11 @@ import Image from "next/image"; import React from "react"; import ProfileTabs from "./ProfileTabs"; +import { useAuthStore } from "../stores/userStore"; const ProfileSidebar = ({ activeTab, setActiveTab }) => { + const user = useAuthStore((state) => state.user); + return (
{ className="absolute bottom-0 right-0" /> -

وليد السيد

+

{user?.name}

UI UX Designer

diff --git a/src/components/profile/ProfileTabs.tsx b/src/components/profile/ProfileTabs.tsx index 2799ecb..0a5eb39 100644 --- a/src/components/profile/ProfileTabs.tsx +++ b/src/components/profile/ProfileTabs.tsx @@ -1,23 +1,59 @@ +'use client'; import React from "react"; import Profile from "../icons/profile/Profile"; import Favorite from "../icons/profile/Favorite"; import Bookmarks from "../icons/profile/Bookmarks"; import MyProducts from "../icons/profile/MyProducts"; import Logout from "../icons/profile/Logout"; +import { logOut } from "@/api/auth/logout"; +import { toast } from "sonner"; +import { useAuthStore } from "../stores/userStore"; +import { useRouter } from "next/navigation"; + +interface ProfileTabsProps { + activeTab: string; + setActiveTab: (tab: string) => void; +} + +interface TabItem { + key: string; + icon: React.ReactNode; + label: string; +} + +const ProfileTabs: React.FC = ({ activeTab, setActiveTab }) => { + const clearUser = useAuthStore((state) => state.clearUser); + const router = useRouter(); + + const handleTabClick = async (tabKey: string): Promise => { + if (tabKey === "logout") { + try { + await logOut(); + clearUser(); + toast.success("Logged out successfully") + router.push("/") + } catch { + toast.error("Logout failed"); + } + } else { + setActiveTab(tabKey); + } + }; + + const tabs: TabItem[] = [ + { key: "profile", icon: , label: "الملف الشخصي" }, + { key: "favorite", icon: , label: "المفضلة" }, + { key: "bookmarks", icon: , label: "المحفوظات" }, + { key: "products", icon: , label: "منتجاتي" }, + { key: "logout", icon: , label: "تسجيل الخروج" }, + ]; -const ProfileTabs = ({ activeTab, setActiveTab }) => { return (
- {[ - { key: "profile", icon: , label: "الملف الشخصي" }, - { key: "favorite", icon: , label: "المفضلة" }, - { key: "bookmarks", icon: , label: "المحفوظات" }, - { key: "products", icon: , label: "منتجاتي" }, - { key: "logout", icon: , label: "تسجيل الخروج" }, - ].map((tab) => ( + {tabs.map((tab: TabItem) => (
setActiveTab(tab.key)} + onClick={() => handleTabClick(tab.key)} className="flex items-center gap-3 cursor-pointer mb-4" > {tab.icon} diff --git a/src/components/stores/userStore.ts b/src/components/stores/userStore.ts index 3f21533..7235ea8 100644 --- a/src/components/stores/userStore.ts +++ b/src/components/stores/userStore.ts @@ -5,6 +5,8 @@ interface User { id: number; name: string; email: string; + phone: string; + job: string; } interface AuthState { diff --git a/src/types/product.ts b/src/types/product.ts index 90ecfb5..987d1fc 100644 --- a/src/types/product.ts +++ b/src/types/product.ts @@ -12,6 +12,11 @@ export type ProductOptionTypes = { in_stock: boolean; }; +export type ProductTypeOption = { + value: string; + in_stock: boolean; +}; + export interface ProductTypes { id: number; name: { @@ -25,6 +30,7 @@ export interface ProductTypes { price: string; discount: string; options: ProductOptionTypes[]; + types: ProductTypeOption[]; category_id: number; brand_id: number | null; is_active: number;