diff --git a/src/App.scss b/src/App.scss index c7e45d54..8a27a8d2 100644 --- a/src/App.scss +++ b/src/App.scss @@ -30,4 +30,5 @@ @import "./assets/styles/tables.scss"; @import "./assets/styles/adminDashboard.scss"; @import "./assets/styles/users.scss"; -@import "./assets//styles/UserProfile.scss" +@import "./assets//styles/UserProfile.scss"; +@import "./assets/styles/SellerSideProduct.scss"; diff --git a/src/assets/styles/SellerLayout.scss b/src/assets/styles/SellerLayout.scss index e91f53aa..a4af7997 100644 --- a/src/assets/styles/SellerLayout.scss +++ b/src/assets/styles/SellerLayout.scss @@ -155,21 +155,100 @@ height: 40%; border-radius: 20px; display: flex; + flex-direction: column; justify-content: center; align-items: center; box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); padding: 2rem; + .profile-image { + border-radius: 50%; + height: 6rem; + border: 0.2rem solid #FF6D18; + width: 6rem; + object-fit: cover; + margin-bottom: 1rem; + } + .profile-name { + font-size: 1.8rem; + font-weight: 600; + color: $text-color; + margin: 0; + } + .profile-edit { + font-size: 1.4rem; + color: $text-color; + background-color: #ffede2; + margin: 0; + cursor: pointer; + border: none; + color: $primary-color; + border-radius: 2rem; + padding: 0.5rem 1.8rem; + margin-top: 1rem; + font-size: 1.4rem; + .icon-edit { + color: $primary-color; + margin-left: 1rem; + } + } + .progress-bar-container { + display: flex; + align-items: center; + font-size: 1.4rem; + margin-top: 1rem; + color: $text-color; + .order-progress { + color: $primary-color; + margin-left: 0.5rem; + margin-right: 0.5rem; + } + } + + .progress-bar { + width: 3rem; + height: 1rem; + background-color: #e0e0e0; + border-radius: 0.5rem; + overflow: hidden; + } + + .progress-bar-fill { + height: 100%; + transition: width 0.3s ease; + } } .right-products { + .loader { + display: flex; + justify-content: center; + align-items: center; + height: 50vh; + } background-color: $white-color; height: 60%; + overflow-y: scroll; + scroll-behavior: smooth; border-radius: 20px; - display: flex; - justify-content: center; - align-items: center; box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); - padding: 2rem; + padding: 1rem; + &::-webkit-scrollbar { + display: none; + } + .right-header { + font-size: 1.4rem; + color: #000; + } + .product-header{ + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.3rem 0.9rem; + border-radius: 2rem; + margin-top: 1rem; + background-color: #d9d9d9; + color: #FF6D18; + } } } } diff --git a/src/assets/styles/SellerSideProduct.scss b/src/assets/styles/SellerSideProduct.scss new file mode 100644 index 00000000..0a3b3513 --- /dev/null +++ b/src/assets/styles/SellerSideProduct.scss @@ -0,0 +1,49 @@ + +.product-card { + display: flex; + align-items: center; + padding: 0.5rem 0.7rem; + border-radius: 1rem; + background-color: #fff; + box-shadow: 0 0.4rem 0.6rem rgba(0, 0, 0, 0.1); + margin: 1rem 0; + + &__number { + font-size: 1.3rem; + font-weight: bold; + margin-right: 1.2rem; + } + + &__image { + width: 3rem; + height: 3rem; + border-radius: 10%; + } + + &__details { + flex-grow: 1; + margin-left: 1rem; + + &__title { + font-size: 16px; + font-weight: bold; + } + } + + &__availability { + font-size: 0.7rem; + font-weight: bold; + padding: 0.2rem 0.6rem; + border-radius: 0.5rem; + + &.available { + color: rgb(3, 216, 3); + background-color: rgba(3, 216, 3, 0.3); + } + + &.unavailable { + color: #fff; + background-color: #f44336; + } + } +} \ No newline at end of file diff --git a/src/components/layout/SellerLayout.tsx b/src/components/layout/SellerLayout.tsx index af655aa7..df0a9bff 100644 --- a/src/components/layout/SellerLayout.tsx +++ b/src/components/layout/SellerLayout.tsx @@ -1,81 +1,188 @@ /* eslint-disable */ -import React, { useState } from 'react'; +import React, { useState, useEffect } from "react"; import { AiFillDashboard } from "react-icons/ai"; import { FaPlusCircle, FaProductHunt } from "react-icons/fa"; +import { FaRegUser } from 'react-icons/fa'; import { IoLogOutSharp } from "react-icons/io5"; -import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom'; -import SellerHeader from './SellerHeader'; -import useSellerAuthCheck from '../../hooks/useSellerAuthCheck'; -import { logout } from '../../store/features/auth/authSlice'; -import { useAppDispatch } from '../../store/store'; -import { PuffLoader } from 'react-spinners'; -import { disconnect } from '../../utils/socket/socket'; +import { Link, Outlet, useLocation, useNavigate } from "react-router-dom"; +import SellerHeader from "./SellerHeader"; +import useSellerAuthCheck from "../../hooks/useSellerAuthCheck"; +import { logout } from "../../store/features/auth/authSlice"; +import { useAppDispatch, useAppSelector } from "../../store/store"; +import { PuffLoader } from "react-spinners"; +import { disconnect } from "../../utils/socket/socket"; +import IconButton from "@mui/material/IconButton"; +import EditIcon from "@mui/icons-material/Edit"; +import SellerSideProduct from "../product/SellerSideProduct"; +import { fetchSellerCollectionProduct } from "../../store/features/product/sellerCollectionProductsSlice"; export const SellerLayout = () => { - const dispatch = useAppDispatch(); - const navigate = useNavigate(); - const {pathname} = useLocation() - const isAuthorized = useSellerAuthCheck(); + const dispatch = useAppDispatch(); + const navigate = useNavigate(); + const { pathname } = useLocation(); + const isAuthorized = useSellerAuthCheck(); + const { user } = useAppSelector((state) => state.auth); + const User: any = { ...user }; + const { data, isLoading, isError } = useAppSelector(state => state.sellerCollectionProducts); + + useEffect(() => { + dispatch(fetchSellerCollectionProduct()); + }, [dispatch]); - const handleLogout = () => { - dispatch(logout()); - disconnect(); - setTimeout(() => { - navigate("/"); - }, 1000); - }; + const handleLogout = () => { + dispatch(logout()); + disconnect(); + setTimeout(() => { + navigate("/"); + }, 1000); + }; - if (!isAuthorized) { - return
- -
; - } + if (!isAuthorized) { return ( -
-
-
-
-
-
- -
-
- -
-
-
- -
-
+
+ +
+ ); + } + + function formatName(name: string) { + const trimmedName = name.trim(); + const formattedName = trimmedName.replace(/\s+/g, '.'); + return formattedName.length > 8 ? formattedName.substring(0, 8) + '...' : formattedName; + } + + const availableProducts = data.products + ?.filter(product => product.status === 'available') + .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) + .slice(0, 5); + + const completionPercentage = 12; + + const getCompletionColor = (percentage) => { + if (percentage >= 80) return "#00FF00"; + if (percentage >= 50) return "#FFFF00"; + return "#FF0000"; // Red + }; + + const progressBarColor = getCompletionColor(completionPercentage); + + return ( +
+
+
+
+
+
+ + + +
+
+ + + +
+
+
+ +
+
+
+
+
+
+
+ + Dashboard + +
+
+ + Products + +
+
+
+

+ Logout +

+
+
+
+
+
+ +
+
+ +
+
+
+ {user && User.profilePicture ? ( + Profile + ) : ( + + )} + + {user ? formatName(User?.firstName || User?.email?.split('@')[0]) : "Account"} + + + Edit Profile + + +
+ Order Completed: {completionPercentage}% +
+
-
-
-
-
- Dashboard -
-
- Products -
-
-
-

Logout

-
-
+
+
+
+

Recent Products

+
+

No

+

Product Name

+

Status

+
+ {isLoading ? ( +
+
-
-
- -
-
- -
-
-
PROFILE
-
PRODUCTS
-
-
-
-
- ); + ) : isError ? ( +
Error loading products.
+ ) : ( + availableProducts?.map((product, index) => ( + + )) + )} +
+
+ + +
+ ); }; diff --git a/src/components/product/SellerSideProduct.tsx b/src/components/product/SellerSideProduct.tsx new file mode 100644 index 00000000..d203e1b5 --- /dev/null +++ b/src/components/product/SellerSideProduct.tsx @@ -0,0 +1,26 @@ +/* eslint-disable */ +import React from 'react'; + +interface ProductCardProps { + number: number; + image: string; + title: string; + availability: string; +} + +const SellerSideProduct: React.FC = ({ number, image, title, availability }) => { + return ( +
+
{number}
+ {title} +
+

{title}

+
+
+ {availability} +
+
+ ); +}; + +export default SellerSideProduct; \ No newline at end of file diff --git a/webpack.dev.config.ts b/webpack.dev.config.ts index 36294abe..551be173 100644 --- a/webpack.dev.config.ts +++ b/webpack.dev.config.ts @@ -84,7 +84,7 @@ const config: Configuration = { historyApiFallback: { disableDotRule: true, }, - port: 9000, + port: 5000, open: true, hot: true, },