A modern, fully-featured e-commerce web application built with React, Redux, and Tailwind CSS. Users can browse products, manage their cart, place orders, and track their purchase history.
🔗 https://e-commerce-topaz-seven-96.vercel.app/
You can log in with the following pre-existing accounts (Password: 123456):
| Role | |
|---|---|
| Customer | customer@commerce.com |
| Store | store@commerce.com |
| Admin | admin@commerce.com |
- Hero Slider (
Hero.jsx) — Full-screen banner with two background images. Left/right arrow buttons allow manual switching between slides. - Editor's Pick —
SubCategoryCard(full height) andHalfSubCategoryCard(half height) components display Men / Women / Accessories / Kids categories as cards. Clicking navigates to the relevant shop page. - Bestseller Products (
BestSellerCard.jsx) — Fetches the top 8 products from the API sorted byrating:descand renders them in a responsive grid usingProductCard. - Carousel (
Carousel.jsx) — Promotional banner with a gradient background, product image, and an "ADD TO CART" button. - Container (
Container.jsx) — "Part of the Neural Universe" feature block with BUY NOW and Learn More buttons. - Blog Section (
BlogCard.jsx) — Three blog cards with image, category tags, date, and comment count. - Brands Strip (
BrandsFav.jsx) — Horizontal list of partner brand logos (AWS, Hooli, Lyft, etc.).
Several complex mechanisms work together on this page:
- Category Cards (
CategoryCard.jsx) — Top 5 highest-rated categories for the active gender filter are displayed at the top. Product count per category is calculated separately by fetching all products once. - View Toggle (
ViewAndFilterButtons.jsx) — Switch between Grid (⊞) and List (☰) views. A sort select handles price ascending/descending and rating ascending/descending. - Filter Panel (
Filter.jsx) — Opens and closes via the "Filter" button with a smooth CSS transition. Includes:- Gender radio buttons — Women / Men
- Category radio buttons — Dynamically updated based on selected gender; clicking updates the URL
- Color selection — 4 color options as styled radio inputs
- Dual-range price slider — Custom min/max slider with two independent thumbs; applies price filter in real time
- Product Listing — Rendered based on
productsDisplaystate:- Grid view:
ProductCard.jsx— Image, name, price, color dots; clicking navigates to the detail page - List view:
ProductCardList.jsx— Horizontal card with image on the left, details on the right, inline "Add to Cart" button, rating, and discount badge
- Grid view:
- Client-Side Filtering — All products are fetched once (
/products?limit=2000); filtering and sorting are handled entirely on the frontend. - Pagination — Dynamically calculated from total products / limit. Shows ellipsis (
...) when there are more than 4 pages. First / numbered pages / Next buttons. - URL Query Params —
filter,sort,limit, andoffsetare written to the URL on every change and survive page refresh.
- Image Area — Main image with two thumbnails below; left/right navigation arrows (currently same image, structure is ready to extend into a full slider).
- Stock Status — Displays
In StockorOut of Stockwith color coding. Stock decrements when added to cart and increments when removed (via custom event:cartStockUpdated). - Color Variants — 4 color options rendered as styled radio inputs.
- Add to Cart (
handleAddCart) — Dispatches ReduxsetCartaction; button color changes for 2 seconds as feedback. - Add to Favorites (
handleLikeClick) — Writes tolocalStorage; updates the header heart icon in real time via custom eventlikedProductsUpdated. - Description / Reviews Tabs — Tabbed content below the product:
- Description: Product description text, word list rendered from description string, shadow-effect image block
- Reviews (
ProductRewievForm.jsx): Review form (star rating, name, email, message, save checkbox). Review cards (ProductReviewCard.jsx) display masked name and email. Reviews are stored inlocalStorage.
- Bestseller Products —
BestSellerCardrenders product recommendations at the bottom of the page.
ShoppingCartCard.jsx— Per product: checkbox to include/exclude from total, product image and name, size label, increment/decrement quantity (auto-removes when count reaches 0), unit price, delete button.- Total Price — Only products with
checked: trueare included in the calculation. SummaryBox.jsx— Subtotal, shipping fee (+$10 when cart is not empty), discount code input (numeric 0–50, calculates percentage), and grand total. The "Confirm Order" button passes price data to the/create-orderpage via routerstate.
Two-tab layout:
Address Tab:
- Saved addresses are listed; a radio button selects the delivery address.
- "Send Invoice to Same Address" checkbox; unchecking reveals a separate billing address column.
- "Add New Address" button opens
AddressForm.jsxas a modal with a backdrop blur overlay. AddressForm.jsx(react-hook-form+react-country-state-city):- Country is fixed to Turkey; province uses
StateSelect, district usesCitySelect— cascading dropdowns that reset when the parent changes. - Phone number is auto-formatted as
(5XX) XXX XX XXon input. - In edit mode, existing address values are pre-filled via
defaultValues. - On save → API POST or PUT → list refreshes → modal closes.
- Country is fixed to Turkey; province uses
- Trash icon next to each address sends a DELETE request immediately.
Payment Tab:
- Saved credit cards are displayed visually using
MyCreditCard.jsx(gradient card design, masked number:1234 **** **** 5678). - Checkbox selects a card; selecting one reveals a CVC/CVV input field below.
- "Pay with a Different Card" toggle opens
AddCreditCard.jsxform:- Card number (digits only, 16 chars), name on card (Turkish/Latin letters only), month/year dropdowns (
CustomDropdown.jsx), CVV. - Shows Update + Delete buttons when a card is selected, Save button otherwise.
- Card number (digits only, 16 chars), name on card (Turkish/Latin letters only), month/year dropdowns (
- 3D Secure checkbox.
- Installment Table — Appears when a card is selected; currently shows single-payment option.
SummaryOrder.jsx— Fixed right panel; the "Confirm Order" button stays disabled until both an address and a card are selected.handleSubmitOrder— Validates address, card, CVC, and that at least one product is checked → POST/order→ on success, shows confirmation screen and clears the cart.
- Displays the order ID and total amount paid.
- "My Orders" and "Home" navigation buttons.
- Fetches all orders from the API (
GET /order). - Table layout: Order No, Date, Amount, Detail toggle.
- Accordion: clicking a row reveals the delivery address (matched from address list by
id) and the list of ordered products. Each product is clickable and links to its detail page.
- The heart button on
ProductDetailsCardadds/removes the product fromlocalStorage. - The header heart icon shows a badge with the count and opens a
LikedProduct.jsxdropdown on click. - Each favorite item shows: product image, name, price, "Add to Cart" button, and "Remove from Favorites" button.
- A custom event (
likedProductsUpdated) keeps the header in sync without page refresh.
- Login (
LoginPage.jsx) —react-hook-formwithmode: onBlur; email + password validation, "Remember Me" checkbox. On success, redirects tolocation.state.from(the page the user came from). - Sign Up (
SignUp.jsx) — Role selector (Customer / Store); selecting Store reveals extra fields: store name, Turkish phone regex, tax number (TXXXXVXXXXXX), IBAN (TRXX...). A toast notification prompts email activation after successful registration. - Token Verification (
verifyUser) — On app load, if a token exists inlocalStorage,GET /verifyis called to restore the session and refresh the token. If no token, the loading screen closes immediately. - Gravatar — User avatar is generated automatically from the MD5 hash of the email address.
- Protected Routes —
/create-orderand/myordersredirect to/loginif no token is present;state.referrerpreserves the return path. - Logout — Clears the token from
localStorage, resets Reduxuser, and navigates to the homepage.
- Sticky top navbar with smooth scroll-to-top on route change (
ScrollTop.jsx). - Logo, desktop nav links (active styling via
NavLink), animated mobile hamburger menu. - Shop Dropdown — Women/Men categories are filtered and sorted by rating using
useMemo. Opens on click (not hover), closes on outside click viauseOnClickOutsidehook. - Search Bar — Animated input that slides down when the search icon is clicked. On submit, dispatches Redux
setFilterand navigates to the shop page. - Cart Dropdown — Clickable only when cart has items; opens
Cart.jsxwith product list and "Go to Cart" / "Complete Order" buttons. - Favorites Dropdown — Heart icon with count badge; opens
LikedProductlist fromlocalStorage. - User Menu — If logged in: avatar + name + hover dropdown (My Orders, Logout). If not: Login / Register links.
- Five independent
useRefinstances +useOnClickOutsideensure each dropdown closes without affecting the others.
| Category | Technology |
|---|---|
| Framework | React 19 |
| Routing | React Router DOM v5 |
| State Management | Redux + Redux Thunk + Redux Logger |
| Form Handling | React Hook Form |
| Styling | Tailwind CSS v4 |
| HTTP Client | Axios |
| Notifications | React Toastify |
| Icons | Lucide React |
| Avatar | Gravatar (via MD5 hash) |
| Location Select | react-country-state-city |
| Build Tool | Vite |
| API | Workintech FE E-Commerce API |
src/
├── components/
│ ├── CreateOrderComponents/ # AddCreditCard, AddressForm, CreditCard, SummaryOrder
│ ├── generalElements/ # CheckBox, CustomDropdown
│ ├── layout/ # Header, Footer, MainLayout
│ ├── ProductDetailsComponents/ # BestSellerCard, ProductDetailsCard, ProductRating,
│ │ # ProductReviewCard, ProductRewievForm
│ ├── ShopComponents/ # BrandsFav, CategoryCard, ViewAndFilterButtons
│ ├── ShoppingCartComponents/ # ShoppingCartCard, SummaryBox
│ ├── TeamPageComponents/
│ ├── BlogCard, Carousel, Cart, CartProductCard
│ ├── Container, Filter, Hero
│ ├── HalfSubCategoryCard, SubCategoryCard
│ ├── LikedProduct, ProductCard, ProductCardList
│ └── ScrollTop
├── data/ # Static content (contact data, etc.)
├── hooks/
│ └── useOnClickOutside.js # Reusable outside-click detection hook
├── icons/
├── pages/
│ ├── AboutPage, BlogPage, ContactPage
│ ├── CreateOrderPage, LoginPage, MainPage
│ ├── PagesPage, PreviousOrders, ProductDetailsPage
│ ├── ShopPage, ShoppingCartPage, SignUp, TeamPage
├── store/
│ ├── actions/ # clientActions, productActions, shoppingCartActions
│ ├── reducers/ # clientReducer, productReducer, shoppingCartReducer
│ ├── types/ # actionTypes.js
│ └── store.js
├── api.js # Axios instance with baseURL config
├── App.jsx # Route definitions + auth guards
└── main.jsx # Redux Provider, BrowserRouter, ToastContainer
- Node.js >= 18
- npm or yarn
# 1. Clone the repository
git clone https://github.com/YOUR_USERNAME/e-commerce.git
cd e-commerce
# 2. Install dependencies
npm install
# 3. Start the development server
npm run devThe app will be available at http://localhost:5173.
| Script | Description |
|---|---|
npm run dev |
Start Vite development server |
npm run build |
Build for production |
npm run preview |
Preview production build locally |
npm run lint |
Run ESLint |
npm run server |
Start JSON Server mock API on port 5000 |
All requests go to:
https://workintech-fe-ecommerce.onrender.com
| Method | Endpoint | Description |
|---|---|---|
| GET | /categories |
Fetch all categories |
| GET | /products |
Fetch products (filter/sort) |
| GET | /products/:id |
Fetch single product |
| POST | /login |
User login |
| POST | /signup |
User registration |
| GET | /verify |
Token verification |
| GET | /user/address |
Fetch saved addresses |
| POST | /user/address |
Add new address |
| PUT | /user/address |
Update address |
| DELETE | /user/address/:id |
Delete address |
| GET | /user/card |
Fetch saved credit cards |
| POST | /user/card |
Add credit card |
| PUT | /user/card |
Update credit card |
| DELETE | /user/card/:id |
Delete credit card |
| POST | /order |
Submit order |
| GET | /order |
Fetch order history |
{
client: {
user: {}, // Logged-in user data
isAuthLoading: true, // True while token is being verified
addressList: [], // Saved delivery addresses
creditCards: [], // Saved credit cards
roles: [],
theme: "light",
language: "tr"
},
product: {
categories: [], // All product categories
productList: [], // Current product list from API
total: 0,
limit: 25,
offset: 0,
filter: "", // Active search filter string
fetchState: "NOT_FETCHED" // FETCHING | FETCHED | FAILED
},
shoppingCart: {
cart: [], // Array of { product, count, checked }
payment: {},
address: {},
orders: [] // Previous orders
}
}| Path | Component | Auth Required |
|---|---|---|
/ |
MainPage | ❌ |
/shop/:gender?/:categoryName?/:categoryId? |
ShopPage | ❌ |
/shop/:gender/:categoryName/:categoryId/:slug/:productId |
ProductDetailsPage | ❌ |
/products/:productId |
ProductDetailsPage | ❌ |
/cart |
ShoppingCartPage | ❌ |
/create-order |
CreateOrderPage | ✅ |
/myorders |
PreviousOrders | ✅ |
/login |
LoginPage | ❌ |
/signup |
SignUp | ❌ |
/about |
AboutPage | ❌ |
/blog |
BlogPage | ❌ |
/contact |
ContactPage | ❌ |
/team |
TeamPage | ❌ |
/pages |
PagesPage | ❌ |
- Liked products are persisted in
localStorageunder the keyliked_products. - Product reviews are persisted in
localStorageunderproduct_reviews. - Auth token is stored in
localStorageundertokenonly when "Remember Me" is checked. - Gravatar avatar URL:
https://www.gravatar.com/avatar/{md5(email)} - Stock sync — When a product is added to or removed from the cart,
window.dispatchEvent(new CustomEvent("cartStockUpdated", { detail: { productId, returnedCount } }))notifiesProductDetailsCardto update stock in real time. - Favorites sync —
window.dispatchEvent(new Event("likedProductsUpdated"))keeps the header badge and dropdown in sync without a page reload. - Category gender codes:
k→ Women,e→ Men
Built as part of the Workintech Full-Stack Bootcamp (Java/React track).
This project is for educational purposes.