├── src ├── vite-env.d.ts ├── main.tsx ├── data │ ├── banners.ts │ └── products.ts ├── components │ ├── layout │ │ ├── CustomCursor.tsx │ │ ├── Footer.tsx │ │ └── Navbar.tsx │ ├── common │ │ ├── BannerCarousel.tsx │ │ ├── Wishlist.tsx │ │ ├── ProductCard.tsx │ │ └── Cart.tsx │ └── admin │ │ └── UserManagement.tsx ├── App.tsx ├── types │ └── index.ts ├── index.css ├── pages │ ├── Home.tsx │ ├── Orders.tsx │ ├── Auth.tsx │ ├── ProductDetail.tsx │ ├── Products.tsx │ ├── AdminDashboard.tsx │ └── Checkout.tsx └── store │ └── useStore.ts ├── postcss.config.js ├── tsconfig.json ├── tailwind.config.js ├── vite.config.ts ├── .gitignore ├── index.html ├── tsconfig.node.json ├── tsconfig.app.json ├── eslint.config.js └── package.json /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | //postcss config -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | // ts config json -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | // tailwind -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react'; 2 | import { createRoot } from 'react-dom/client'; 3 | import App from './App.tsx'; 4 | import './index.css'; 5 | 6 | createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | optimizeDeps: { 8 | exclude: ['lucide-react'], 9 | }, 10 | }); 11 | //vite config -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | #gitignore 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | .env 26 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Shop Market - Fashion eCommerce Website 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | {/* Ts config node json */ 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "lib": ["ES2023"], 5 | "module": "ESNext", 6 | "skipLibCheck": true, 7 | 8 | /* Bundler mode */ 9 | "moduleResolution": "bundler", 10 | "allowImportingTsExtensions": true, 11 | "isolatedModules": true, 12 | "moduleDetection": "force", 13 | "noEmit": true, 14 | 15 | /* Linting */ 16 | "strict": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "noFallthroughCasesInSwitch": true 20 | }, 21 | "include": ["vite.config.ts"] 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | {/* ts config app json */ 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"] 24 | } 25 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js'; 2 | import globals from 'globals'; 3 | import reactHooks from 'eslint-plugin-react-hooks'; 4 | import reactRefresh from 'eslint-plugin-react-refresh'; 5 | import tseslint from 'typescript-eslint'; 6 | // eslint config 7 | export default tseslint.config( 8 | { ignores: ['dist'] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ['**/*.{ts,tsx}'], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | 'react-hooks': reactHooks, 18 | 'react-refresh': reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | 'react-refresh/only-export-components': [ 23 | 'warn', 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | } 28 | ); 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-react-typescript-starter", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@headlessui/react": "^2.2.4", 14 | "@heroicons/react": "^2.2.0", 15 | "@hookform/resolvers": "^5.1.1", 16 | "@types/react-router-dom": "^5.3.3", 17 | "framer-motion": "^12.23.0", 18 | "lucide-react": "^0.344.0", 19 | "react": "^18.3.1", 20 | "react-dom": "^18.3.1", 21 | "react-hook-form": "^7.60.0", 22 | "react-hot-toast": "^2.5.2", 23 | "react-router-dom": "^7.6.3", 24 | "swiper": "^11.2.10", 25 | "yup": "^1.6.1", 26 | "zustand": "^5.0.6" 27 | }, 28 | "devDependencies": { 29 | "@eslint/js": "^9.9.1", 30 | "@types/react": "^18.3.5", 31 | "@types/react-dom": "^18.3.0", 32 | "@vitejs/plugin-react": "^4.3.1", 33 | "autoprefixer": "^10.4.18", 34 | "eslint": "^9.9.1", 35 | "eslint-plugin-react-hooks": "^5.1.0-rc.0", 36 | "eslint-plugin-react-refresh": "^0.4.11", 37 | "globals": "^15.9.0", 38 | "postcss": "^8.4.35", 39 | "tailwindcss": "^3.4.1", 40 | "typescript": "^5.5.3", 41 | "typescript-eslint": "^8.3.0", 42 | "vite": "^5.4.2" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/data/banners.ts: -------------------------------------------------------------------------------- 1 | import { Banner } from '../types'; 2 | 3 | export const banners: Banner[] = [ 4 | { 5 | id: 'banner-1', 6 | title: 'Summer Collection 2024', 7 | subtitle: 'Discover the latest trends in summer fashion', 8 | image: 'https://images.pexels.com/photos/1536619/pexels-photo-1536619.jpeg?auto=compress&cs=tinysrgb&w=1200', 9 | link: '/products?category=summer', 10 | buttonText: 'Shop Now', 11 | isActive: true 12 | }, 13 | { 14 | id: 'banner-2', 15 | title: 'Men\'s Premium Collection', 16 | subtitle: 'Elevate your style with our premium menswear', 17 | image: 'https://images.pexels.com/photos/1040945/pexels-photo-1040945.jpeg?auto=compress&cs=tinysrgb&w=1200', 18 | link: '/men', 19 | buttonText: 'Explore Men\'s', 20 | isActive: true 21 | }, 22 | { 23 | id: 'banner-3', 24 | title: 'Women\'s Exclusive Deals', 25 | subtitle: 'Up to 50% off on selected women\'s fashion', 26 | image: 'https://images.pexels.com/photos/1457983/pexels-photo-1457983.jpeg?auto=compress&cs=tinysrgb&w=1200', 27 | link: '/women', 28 | buttonText: 'Shop Women\'s', 29 | isActive: true 30 | }, 31 | { 32 | id: 'banner-4', 33 | title: 'New Arrivals', 34 | subtitle: 'Be the first to wear the latest fashion trends', 35 | image: 'https://images.pexels.com/photos/2827400/pexels-photo-2827400.jpeg?auto=compress&cs=tinysrgb&w=1200', 36 | link: '/products?filter=new', 37 | buttonText: 'View New', 38 | isActive: true 39 | } 40 | ]; -------------------------------------------------------------------------------- /src/components/layout/CustomCursor.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { motion } from 'framer-motion'; 3 | 4 | export const CustomCursor: React.FC = () => { 5 | const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); 6 | const [isHovering, setIsHovering] = useState(false); 7 | 8 | useEffect(() => { 9 | const updateMousePosition = (e: MouseEvent) => { 10 | setMousePosition({ x: e.clientX, y: e.clientY }); 11 | }; 12 | 13 | const handleMouseOver = (e: MouseEvent) => { 14 | const target = e.target as HTMLElement; 15 | if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.closest('button') || target.closest('a')) { 16 | setIsHovering(true); 17 | } else { 18 | setIsHovering(false); 19 | } 20 | }; 21 | 22 | window.addEventListener('mousemove', updateMousePosition); 23 | window.addEventListener('mouseover', handleMouseOver); 24 | 25 | return () => { 26 | window.removeEventListener('mousemove', updateMousePosition); 27 | window.removeEventListener('mouseover', handleMouseOver); 28 | }; 29 | }, []); 30 | 31 | return ( 32 | <> 33 | 42 | 50 | 51 | ); 52 | }; -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; 3 | import { Toaster } from 'react-hot-toast'; 4 | import { useStore } from './store/useStore'; 5 | import { Navbar } from './components/layout/Navbar'; 6 | import { Footer } from './components/layout/Footer'; 7 | import { Cart } from './components/common/Cart'; 8 | import { Wishlist } from './components/common/Wishlist'; 9 | import { Home } from './pages/Home'; 10 | import { Products } from './pages/Products'; 11 | import { ProductDetail } from './pages/ProductDetail'; 12 | import { Orders } from './pages/Orders'; 13 | import { Checkout } from './pages/Checkout'; 14 | import { Auth } from './pages/Auth'; 15 | import { AdminDashboard } from './pages/AdminDashboard'; 16 | 17 | function App() { 18 | const { isDarkMode } = useStore(); 19 | 20 | useEffect(() => { 21 | if (isDarkMode) { 22 | document.documentElement.classList.add('dark'); 23 | } else { 24 | document.documentElement.classList.remove('dark'); 25 | } 26 | }, [isDarkMode]); 27 | 28 | return ( 29 | 30 |
31 | 32 |
33 | 34 | } /> 35 | } /> 36 | } /> 37 | } /> 38 | } /> 39 | } /> 40 | } /> 41 | } /> 42 | } /> 43 | Wishlist page - use the wishlist sidebar instead!
} /> 44 | 45 | 46 |