Skip to content

Commit

Permalink
fix(profiles) #187300200 Users should be able to view and edit their …
Browse files Browse the repository at this point in the history
…profiles

-addresses all required changes on wishlist
-User now he can view all products he added on wishlist
-Fixed margin between wishlist component and Footer
-Worked on feedback given on good and useful user experience
  • Loading branch information
amiparadis250 committed Jul 5, 2024
1 parent ec99bd2 commit 4929e06
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/app/(profile)/profile-edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ const UserProfileForm: React.FC = () => {
</div>
<div className="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
<button type="button" className="w-full sm:w-1/2 bg-white text-gray-700 border border-gray-300 px-16 py-2 rounded hover:bg-gray-100 transition duration-300">
Cancel
<a href="/profile">Cancel</a>
</button>
<button
type="submit"
Expand Down
9 changes: 5 additions & 4 deletions src/app/(profile)/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ const ProfilePage = () => {
<div className="bg-gray-100 w-full flex flex-col items-center">
<Header />
<ProfileHeader />
<div className='w-full max-w-7xl px-4 mt-4'>
<div className='w-full max-w-7xl px-4 mt-4 mb-4'>
<div className='grid grid-cols-1 md:grid-cols-4 gap-4'>
<div className='md:col-span-1'>
<About />
</div>
<div className='md:col-span-2'>
<div className='md:col-span-2 mb-4'>
<Wishlist />
</div>
<div className='md:col-span-1 flex flex-col gap-4'>
<div className='md:col-span-1 flex flex-col gap-4 mb-4'>
<Order />
<ActiveUser />
{/* <ActiveUser /> */}
</div>
</div>
</div>

<Footer />
</div>
);
Expand Down
5 changes: 4 additions & 1 deletion src/components/profile/About.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"use client";
import React, { useEffect } from 'react';
import { User, Cake } from 'lucide-react';
import { User, Cake, Award } from 'lucide-react';
import { FaUser, FaEnvelope } from "react-icons/fa";
import { FaLocationDot, FaPhone } from "react-icons/fa6";
import { useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState } from '@/redux/store';
import { getUserProfile } from '@/redux/slices/profileSlice';
import request from '@/utils/axios';

function About() {
const dispatch = useDispatch<AppDispatch>();
Expand All @@ -18,6 +19,8 @@ function About() {
fetchData();
}, [dispatch]);



if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!user) return <div>No user found</div>;
Expand Down
19 changes: 18 additions & 1 deletion src/components/profile/Order.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import React from 'react'
"use client";
import React, { useEffect, useState } from 'react'
import request from '@/utils/axios';




function Order() {
// const [orderss, setOrders] = useState<Orders[]>([]);
// useEffect(() => {
// const fetchData = async () => {
// const response: any = await request.get('/orders');
// setOrders(response.orders);
// };
// fetchData();
// }, [])
const orders: any = [
{
name: "Sneakers N12",
Expand All @@ -14,6 +28,9 @@ function Order() {
desc: "tkacheanton dress"
}
]
useEffect(() => {

}, [])
return (
<div className='bg-white shadow-md rounded-lg pl-10 pb-4'>
<div className='w-[100%] py-4 '>
Expand Down
158 changes: 97 additions & 61 deletions src/components/profile/wishlist.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
"use client"
import React, { useEffect } from 'react';
'use client';

import React, { useEffect, useState } from 'react';
import { HiDotsHorizontal } from "react-icons/hi";
import { FaRegHeart } from "react-icons/fa";
import { VscTag } from "react-icons/vsc";
import { useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState } from '@/redux/store';
import { getUserProfile } from '@/redux/slices/profileSlice';
import request from '@/utils/axios';
import { Cylinder, Trash, Loader } from 'lucide-react';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import Link from 'next/link';

interface Product {
id: string;
productThumbnail: string;
stockLevel: number;
productName: string;
productPrice: number;
productCurrency: string;
}

interface Wish {
id: string;
userId: string;
productId: string;
createdAt: string;
updatedAt: string;
product: Product;
}

function Wishlist() {
const Wishlist: React.FC = () => {
const dispatch = useDispatch<AppDispatch>();
const { user, loading, error } = useSelector((state: RootState) => state.userProfile);
const [wishlist, setWishlist] = useState<Wish[]>([]);
const [loadingWishId, setLoadingWishId] = useState<string | null>(null);

useEffect(() => {
const fetchData = async () => {
Expand All @@ -18,78 +43,89 @@ function Wishlist() {
fetchData();
}, [dispatch]);

const getWishlist = async () => {
try {
const response: any = await request.get('/wishes');
setWishlist(response.wishes);
} catch (err) {
console.error(err);
}
};

useEffect(() => {
getWishlist();
}, []);

const removeWish = async (wishId: string) => {
setLoadingWishId(wishId);
try {
await request.post('/wishes', { productId: wishId });
toast.success('Wishlist item removed successfully');
getWishlist();
} catch (err) {
console.error(err);
toast.error('Failed to remove wishlist item');
} finally {
setLoadingWishId(null);
}
}

if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!user) return <div>No user found</div>;

const wishlist = [
{
productName: "Snakers 270",
image: "https://i5.walmartimages.com/seo/LEEy-world-Toddler-Shoes-Children-Mesh-Shoes-Spring-and-Autumn-New-Boys-Korean-Casual-Girls-Breathable-Sneakers-Sports-Shoes-for-Girls-Blue_31b4bad2-f738-45e3-87e5-884066b97e9a.3da4fe17d1b33554816beee33dd674f9.jpeg",
seller: "Kayigamba Blair",
wishes: "1,489",
price: "100",
currency: "$"
},
{
productName: "Snakers 270",
image: "https://www.campusshoes.com/cdn/shop/products/FIRST_11G-787_WHT-SIL-B.ORG.jpg?v=1705644651",
seller: "Kayigamba Blair",
wishes: "1,489",
price: "100",
currency: "$"
},
{
productName: "Snakers 270",
image: "https://cdn.thewirecutter.com/wp-content/media/2023/09/running-shoes-2048px-5946.jpg?auto=webp&quality=75&width=1024",
seller: "Kayigamba Blair",
wishes: "1,489",
price: "100",
currency: "$"
}
];

return (
<div className='bg-white shadow-md rounded-lg'>
<div className='w-[100%] pl-16 py-4 border-b-[1px] mb-4'>
<div className='w-full pl-16 py-4 border-b mb-4'>
<h3 className='font-semibold text-primaryBlue'>Wished Products</h3>
</div>
<div className='flex flex-col gap-8 px-16'>
{wishlist.map((item, index) => (
<div key={index} className='flex flex-col items-center gap-4'>
<div className='flex justify-between w-[100%] items-center'>
<div className='flex justify-center items-center gap-3'>
{user.User && (
<img src={user.User.profileImage} alt='Profile' width={60} height={60} className='rounded-full' />
)}
<div className='flex flex-col'>
<span className='text-blue-500'>{user.User?.firstName} {user.User?.lastName}</span>
<span className='text-[0.6rem] text-green-500'>Your Wishes</span>
</div>
{wishlist.length === 0 ? (
<div className='text-center py-8 text-gray-500'>
Your wishlist will appear here
</div>
) : (
wishlist.map((wish) => (
<div key={wish.id} className='flex flex-col items-center gap-4 border-b pb-4'>
<div className='flex justify-between w-full items-center'>
{/* <HiDotsHorizontal className='text-green-500 text-2xl font-semibold' /> */}
<button
onClick={() => removeWish(wish.productId)}
className='text-red-500 text-2xl font-semibold'
disabled={loadingWishId === wish.productId}
>
{loadingWishId === wish.productId ? <Loader className='animate-spin' /> : <Trash />}
</button>
</div>
<HiDotsHorizontal className='text-green-500 text-[1.5rem] font-semibold' />
</div>
<div style={{ backgroundImage: `url(${item.image})` }} className='w-full h-52 rounded-md bg-cover bg-center'></div>
<div className='flex justify-between w-full text-[.8rem] text-blue-900'>
<span className='font-semibold'>{item.productName}</span>
<span>Seller: {item.seller}</span>
<span>{item.price}{item.currency}</span>
</div>
<div className='flex w-full gap-8 justify-start items-center'>
<div className='flex items-center justify-center gap-1'>
<FaRegHeart className='text-[1.3rem] text-green-500' />
<span className='text-secondaryBlue'>{item.wishes}</span>
<div className='w-full aspect-video rounded-md overflow-hidden'>
<Link href={`/products/${wish.product.id}`}>
<img
src={wish.product.productThumbnail}
alt={wish.product.productName}
className='w-full h-full object-contain'
/>
</Link>
</div>
<div className='flex items-center justify-center gap-1'>
<VscTag className='text-[1.3rem] text-green-500' />
<span className='text-secondaryBlue'>{item.price}{item.currency}</span>
<div className='w-full text-blue-900 flex justify-between items-center text-sm'>
<span className='font-semibold text-lg'>{wish.product.productName}</span>
<div className='flex gap-8'>
<div className='flex items-center gap-1'>
<Cylinder className='text-2xl text-green-500' />
<span className='text-secondaryBlue'>{wish.product.stockLevel}</span>
</div>
<div className='flex items-center gap-1'>
<VscTag className='text-2xl text-green-500' />
<span className='text-secondaryBlue'>{wish.product.productPrice} {wish.product.productCurrency}</span>
</div>
</div>
</div>
</div>
</div>
))}
))
)}
</div>
<ToastContainer />
</div>
);
}

export default Wishlist;
export default Wishlist;

0 comments on commit 4929e06

Please sign in to comment.