diff --git a/client/index.html b/client/index.html index b8b14bc..e2a4ab6 100644 --- a/client/index.html +++ b/client/index.html @@ -4,6 +4,21 @@ ShopCo + + + + + + + + + + + + + + +
diff --git a/client/package.json b/client/package.json index aaffa5c..8f9ea8f 100644 --- a/client/package.json +++ b/client/package.json @@ -12,6 +12,7 @@ "dependencies": { "@tanstack/react-query": "^5.90.2", "axios": "^1.12.2", + "lucide-react": "^0.544.0", "react": "^19.1.1", "react-dom": "^19.1.1", "react-query": "^3.39.3", diff --git a/client/public/favicon.ico b/client/public/favicon.ico new file mode 100644 index 0000000..a946ab2 Binary files /dev/null and b/client/public/favicon.ico differ diff --git a/client/src/App.tsx b/client/src/App.tsx index f07978e..cb7e3c1 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,19 +1,25 @@ import { Routes, Route } from 'react-router-dom' -import Landing from './pages/Landing' -import ApiStatus from './components/ApiStatus' +import Home from './pages/home' +// import ApiStatus from './components/ApiStatus' +import Header from './components/layout/Header' function App() { return ( -
- {/* API Status Indicator */} -
- -
+
+
+ {/* API Status Indicator - Mobile responsive positioning */} + {/*
+
+ +
+
*/} - {/* Main App Routes */} - - } /> - + {/* Main App Routes with minimal top padding to account for fixed header */} +
+ + } /> + +
) } diff --git a/client/src/assets/images/Browse/Casual.png b/client/src/assets/images/Browse/Casual.png new file mode 100644 index 0000000..6d66a62 Binary files /dev/null and b/client/src/assets/images/Browse/Casual.png differ diff --git a/client/src/assets/images/Browse/Formal.png b/client/src/assets/images/Browse/Formal.png new file mode 100644 index 0000000..8138db9 Binary files /dev/null and b/client/src/assets/images/Browse/Formal.png differ diff --git a/client/src/assets/images/Browse/Gym.png b/client/src/assets/images/Browse/Gym.png new file mode 100644 index 0000000..73f8f0b Binary files /dev/null and b/client/src/assets/images/Browse/Gym.png differ diff --git a/client/src/assets/images/Browse/Party.png b/client/src/assets/images/Browse/Party.png new file mode 100644 index 0000000..e0fbb9f Binary files /dev/null and b/client/src/assets/images/Browse/Party.png differ diff --git a/client/src/assets/images/brands/CalvinKlein.png b/client/src/assets/images/brands/CalvinKlein.png new file mode 100644 index 0000000..a18ab75 Binary files /dev/null and b/client/src/assets/images/brands/CalvinKlein.png differ diff --git a/client/src/assets/images/brands/Gucci.png b/client/src/assets/images/brands/Gucci.png new file mode 100644 index 0000000..0814692 Binary files /dev/null and b/client/src/assets/images/brands/Gucci.png differ diff --git a/client/src/assets/images/brands/Prada.png b/client/src/assets/images/brands/Prada.png new file mode 100644 index 0000000..5c8a18c Binary files /dev/null and b/client/src/assets/images/brands/Prada.png differ diff --git a/client/src/assets/images/brands/Versace.png b/client/src/assets/images/brands/Versace.png new file mode 100644 index 0000000..2341bff Binary files /dev/null and b/client/src/assets/images/brands/Versace.png differ diff --git a/client/src/assets/images/brands/Zara.png b/client/src/assets/images/brands/Zara.png new file mode 100644 index 0000000..6de553d Binary files /dev/null and b/client/src/assets/images/brands/Zara.png differ diff --git a/client/src/assets/images/hero/hero_image.png b/client/src/assets/images/hero/hero_image.png new file mode 100644 index 0000000..a73ccf4 Binary files /dev/null and b/client/src/assets/images/hero/hero_image.png differ diff --git a/client/src/assets/images/icons/star_big.png b/client/src/assets/images/icons/star_big.png new file mode 100644 index 0000000..86d3acc Binary files /dev/null and b/client/src/assets/images/icons/star_big.png differ diff --git a/client/src/assets/images/icons/star_small.png b/client/src/assets/images/icons/star_small.png new file mode 100644 index 0000000..1ee4506 Binary files /dev/null and b/client/src/assets/images/icons/star_small.png differ diff --git a/client/src/assets/images/products/Bermuda.png b/client/src/assets/images/products/Bermuda.png new file mode 100644 index 0000000..b227c00 Binary files /dev/null and b/client/src/assets/images/products/Bermuda.png differ diff --git a/client/src/assets/images/products/CheckeredShirt.png b/client/src/assets/images/products/CheckeredShirt.png new file mode 100644 index 0000000..27dc649 Binary files /dev/null and b/client/src/assets/images/products/CheckeredShirt.png differ diff --git a/client/src/assets/images/products/Courage.png b/client/src/assets/images/products/Courage.png new file mode 100644 index 0000000..70ca7b5 Binary files /dev/null and b/client/src/assets/images/products/Courage.png differ diff --git a/client/src/assets/images/products/FadedSkinnyJeans.png b/client/src/assets/images/products/FadedSkinnyJeans.png new file mode 100644 index 0000000..c78d504 Binary files /dev/null and b/client/src/assets/images/products/FadedSkinnyJeans.png differ diff --git a/client/src/assets/images/products/SkinnyFitJeans.png b/client/src/assets/images/products/SkinnyFitJeans.png new file mode 100644 index 0000000..f885ec6 Binary files /dev/null and b/client/src/assets/images/products/SkinnyFitJeans.png differ diff --git a/client/src/assets/images/products/SleevStripedT.png b/client/src/assets/images/products/SleevStripedT.png new file mode 100644 index 0000000..5f2e7aa Binary files /dev/null and b/client/src/assets/images/products/SleevStripedT.png differ diff --git a/client/src/assets/images/products/TapeDetails.png b/client/src/assets/images/products/TapeDetails.png new file mode 100644 index 0000000..95e3b4a Binary files /dev/null and b/client/src/assets/images/products/TapeDetails.png differ diff --git a/client/src/assets/images/products/VerticalStripped.png b/client/src/assets/images/products/VerticalStripped.png new file mode 100644 index 0000000..2aa190d Binary files /dev/null and b/client/src/assets/images/products/VerticalStripped.png differ diff --git a/client/src/components/ApiStatus.tsx b/client/src/components/ApiStatus.tsx index b2e5b7f..49e666d 100644 --- a/client/src/components/ApiStatus.tsx +++ b/client/src/components/ApiStatus.tsx @@ -79,18 +79,18 @@ const ApiStatus: React.FC = ({ showDetails = false }) => { }; return ( -
- {getStatusIcon()} - {getStatusText()} +
+ {getStatusIcon()} + {getStatusText()} {showDetails && lastChecked && ( - + (Last checked: {lastChecked.toLocaleTimeString()}) )} {!isHealthy && ( +
+
+
+ + + ); +}; + +export default Newsletter; diff --git a/client/src/components/layout/Footer.tsx b/client/src/components/layout/Footer.tsx new file mode 100644 index 0000000..6ab6c3a --- /dev/null +++ b/client/src/components/layout/Footer.tsx @@ -0,0 +1,111 @@ +const Footer = () => { + return ( + + ); +}; + +export default Footer; diff --git a/client/src/components/layout/Header.tsx b/client/src/components/layout/Header.tsx new file mode 100644 index 0000000..fed3451 --- /dev/null +++ b/client/src/components/layout/Header.tsx @@ -0,0 +1,97 @@ +import { useState } from 'react' +import { Link } from 'react-router-dom' +import { Menu, X, Search, ShoppingCart, User, ChevronDown } from 'lucide-react' + +export default function Header() { + const [isOpen, setIsOpen] = useState(false) + + return ( +
+
+
+ {/* Left: Mobile menu button & Logo */} +
+ + + {/* Logo */} + + SHOP.CO + + {/* Desktop nav */} + +
+ + {/* Center: Search (desktop only) */} +
+
+ + + + +
+
+ + {/* Right: Icons */} +
+ {/* Search icon on mobile */} + + + +
+
+
+ + {/* Mobile dropdown overlay */} +
+
+ Shop + On Sale + New Arrivals + Brands +
+
+ + + + +
+
+
+
+
+ ) +} diff --git a/client/src/index.css b/client/src/index.css index 57351d4..06c1775 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,5 +1,8 @@ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); +@import url(https://db.onlinewebfonts.com/c/f1fcc5aed1e20fc0cdb9f8a7573625bd?family=Integral+CF+Regular); +@import url('https://api.fontshare.com/v2/css?f[]=satoshi@300,301,400,401,500,501,700,701,900,901,1,2&display=swap'); + @tailwind base; @tailwind components; @tailwind utilities; diff --git a/client/src/pages/Landing.tsx b/client/src/pages/Landing.tsx index ee63b86..32b3ac1 100644 --- a/client/src/pages/Landing.tsx +++ b/client/src/pages/Landing.tsx @@ -5,55 +5,62 @@ export default function Landing() { return (
-
- {/* Welcome Message */} + {/* Mobile-first container with minimal top padding */} +
+ {/* Welcome Message - Mobile optimized */} {isAuthenticated && user && ( -
-
+
+
👋 Welcome back, {user.firstName}!
)} - {/* Hero */} -
-

+ {/* Hero Section - Mobile-first responsive */} +
+ {/* Mobile: smaller text, tablet/desktop: larger */} +

Discover Products You'll Love

-

+

Curated selections, great prices, and a smooth shopping experience.

-
- -
- {/* Features */} -
-
-
🚚
-

Free Shipping

-

Enjoy free shipping on orders over $50 across select regions.

+ {/* Features Section - Mobile-first grid */} +
+ {/* Feature Card 1 */} +
+
🚚
+

Free Shipping

+

Enjoy free shipping on orders over $50 across select regions.

-
-
🔒
-

Secure Checkout

-

Industry-standard encryption to keep your payments and data safe.

+ + {/* Feature Card 2 */} +
+
🔒
+

Secure Checkout

+

Industry-standard encryption to keep your payments and data safe.

-
-
📦
-

Easy Returns

-

Hassle-free returns within 30 days on eligible items.

+ + {/* Feature Card 3 */} +
+
📦
+

Easy Returns

+

Hassle-free returns within 30 days on eligible items.

) } - - diff --git a/client/src/pages/home/index.tsx b/client/src/pages/home/index.tsx new file mode 100644 index 0000000..ef6feff --- /dev/null +++ b/client/src/pages/home/index.tsx @@ -0,0 +1,21 @@ +import Hero from './sections/Hero' +import Brands from './sections/Brands' +import NewArrivals from './sections/NewArrivals' +import TopSelling from './sections/TopSelling' +import Newsletter from '../../components/Newsletter' +import Footer from '../../components/layout/Footer' + +export default function Home() { + return ( +
+ + + + + +
+
+ ) +} + + diff --git a/client/src/pages/home/sections/Brands.tsx b/client/src/pages/home/sections/Brands.tsx new file mode 100644 index 0000000..0cc940b --- /dev/null +++ b/client/src/pages/home/sections/Brands.tsx @@ -0,0 +1,35 @@ +import versaceLogo from '../../../assets/images/brands/Versace.png' +import zaraLogo from '../../../assets/images/brands/Zara.png' +import gucciLogo from '../../../assets/images/brands/Gucci.png' +import pradaLogo from '../../../assets/images/brands/Prada.png' +import calvinKleinLogo from '../../../assets/images/brands/CalvinKlein.png' + +const Brands = () => { + const brands = [ + { name: 'Versace', logo: versaceLogo }, + { name: 'Zara', logo: zaraLogo }, + { name: 'Gucci', logo: gucciLogo }, + { name: 'Prada', logo: pradaLogo }, + { name: 'Calvin Klein', logo: calvinKleinLogo }, + ] + + return ( +
+
+
+ {brands.map((brand) => ( +
+ {brand.name} +
+ ))} +
+
+
+ ) +} + +export default Brands \ No newline at end of file diff --git a/client/src/pages/home/sections/Hero.tsx b/client/src/pages/home/sections/Hero.tsx new file mode 100644 index 0000000..c21840f --- /dev/null +++ b/client/src/pages/home/sections/Hero.tsx @@ -0,0 +1,55 @@ +import heroImage from '../../../assets/images/hero/hero_image.png' + +export default function Hero() { + return ( +
+ {/* Background image */} + + + {/* Content */} +
+
+

+ FIND CLOTHES +
+ THAT MATCHES +
+ YOUR STYLE +

+

+ Browse through our diverse range of meticulously crafted garments, designed + to bring out your individuality and cater to your sense of style. +

+
+ +
+ + {/* Stats */} +
+
+
200+
+
International Brands
+
+
+
2,000+
+
High-Quality Products
+
+
+
30,000+
+
Happy Customers
+
+
+
+
+
+ ) +} + + diff --git a/client/src/pages/home/sections/NewArrivals.tsx b/client/src/pages/home/sections/NewArrivals.tsx new file mode 100644 index 0000000..bf89a4a --- /dev/null +++ b/client/src/pages/home/sections/NewArrivals.tsx @@ -0,0 +1,122 @@ +import tapeDetailsImg from '../../../assets/images/products/TapeDetails.png' +import skinnyFitJeansImg from '../../../assets/images/products/SkinnyFitJeans.png' +import checkeredShirtImg from '../../../assets/images/products/CheckeredShirt.png' +import sleeveStripedImg from '../../../assets/images/products/SleevStripedT.png' + +interface Product { + id: number; + name: string; + price: number; + originalPrice?: number; + discount?: number; + rating: number; + image: string; +} + +const NewArrivals = () => { + // Hardcoded data - easily replaceable with API data + const products: Product[] = [ + { + id: 1, + name: "T-shirt with Tape Details", + price: 120, + rating: 4.5, + image: tapeDetailsImg + }, + { + id: 2, + name: "Skinny Fit Jeans", + price: 240, + originalPrice: 260, + discount: 20, + rating: 3.5, + image: skinnyFitJeansImg + }, + { + id: 3, + name: "Checkered Shirt", + price: 180, + rating: 4.5, + image: checkeredShirtImg + }, + { + id: 4, + name: "Sleeve Striped T-shirt", + price: 130, + originalPrice: 160, + discount: 30, + rating: 4.5, + image: sleeveStripedImg + } + ]; + + const renderStars = (rating: number) => { + return Array.from({ length: 5 }, (_, i) => ( + + ★ + + )); + }; + + return ( +
+
+ {/* Section Title */} +
+

NEW ARRIVALS

+
+ + {/* Products Grid */} +
+ {products.map((product) => ( +
+ {/* Product Image */} +
+ {product.name} +
+ + {/* Product Info */} +
+

{product.name}

+ + {/* Rating */} +
+
+ {renderStars(product.rating)} +
+ {product.rating}/5 +
+ + {/* Price */} +
+ ${product.price} + {product.originalPrice && ( + <> + ${product.originalPrice} + + -{product.discount}% + + + )} +
+
+
+ ))} +
+ + {/* View All Button */} +
+ +
+
+
+ ); +}; + +export default NewArrivals; \ No newline at end of file diff --git a/client/src/pages/home/sections/TopSelling.tsx b/client/src/pages/home/sections/TopSelling.tsx new file mode 100644 index 0000000..548acf6 --- /dev/null +++ b/client/src/pages/home/sections/TopSelling.tsx @@ -0,0 +1,120 @@ +import verticalStripedImg from '../../../assets/images/products/VerticalStripped.png' +import courageImg from '../../../assets/images/products/Courage.png' +import bermudaImg from '../../../assets/images/products/Bermuda.png' +import fadedSkinnyJeansImg from '../../../assets/images/products/FadedSkinnyJeans.png' + +interface Product { + id: number; + name: string; + price: number; + originalPrice?: number; + discount?: number; + rating: number; + image: string; +} + +const TopSelling = () => { + // Hardcoded data - easily replaceable with API data + const products: Product[] = [ + { + id: 1, + name: "Vertical Striped Shirt", + price: 212, + originalPrice: 232, + discount: 20, + rating: 5.0, + image: verticalStripedImg + }, + { + id: 2, + name: "Courage Graphic T-shirt", + price: 145, + rating: 4.0, + image: courageImg + }, + { + id: 3, + name: "Loose Fit Bermuda Shorts", + price: 80, + rating: 3.0, + image: bermudaImg + }, + { + id: 4, + name: "Faded Skinny Jeans", + price: 210, + rating: 4.5, + image: fadedSkinnyJeansImg + } + ]; + + const renderStars = (rating: number) => { + return Array.from({ length: 5 }, (_, i) => ( + + ★ + + )); + }; + + return ( +
+
+ {/* Section Title */} +
+

TOP SELLING

+
+ + {/* Products Grid */} +
+ {products.map((product) => ( +
+ {/* Product Image */} +
+ {product.name} +
+ + {/* Product Info */} +
+

{product.name}

+ + {/* Rating */} +
+
+ {renderStars(product.rating)} +
+ {product.rating}/5 +
+ + {/* Price */} +
+ ${product.price} + {product.originalPrice && ( + <> + ${product.originalPrice} + + -{product.discount}% + + + )} +
+
+
+ ))} +
+ + {/* View All Button */} +
+ +
+
+
+ ); +}; + +export default TopSelling; \ No newline at end of file diff --git a/client/tailwind.config.js b/client/tailwind.config.js index 97b487f..fc00201 100644 --- a/client/tailwind.config.js +++ b/client/tailwind.config.js @@ -33,7 +33,11 @@ export default { } }, fontFamily: { - sans: ['Inter', 'system-ui', 'sans-serif'], + // Satoshi for UI text (body, paragraphs, buttons, etc.) + sans: ['Satoshi', 'Inter', 'system-ui', 'sans-serif'], + + // Integral CF for headings + heading: ['Integral CF Regular', 'Inter', 'system-ui', 'sans-serif'], }, }, }, diff --git a/client/yarn.lock b/client/yarn.lock index e6df832..9c42c6e 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -1657,6 +1657,11 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lucide-react@^0.544.0: + version "0.544.0" + resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.544.0.tgz#4719953c10fd53a64dd8343bb0ed16ec79f3eeef" + integrity sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw== + match-sorter@^6.0.2: version "6.4.0" resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.4.0.tgz#ae9c166cb3c9efd337690b3160c0e28cb8377c13"