db hanta ktr mnhadchi chne bghiti

This commit is contained in:
2026-03-24 09:25:45 +01:00
parent f986e2387f
commit d957fa4cd3
23 changed files with 844 additions and 89 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
frontend/node_modules/
frontend/dist/
frontend/.vite/
frontend/*.tsbuildinfo

View File

@@ -14,10 +14,10 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("ShopAPI")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1d2f7c0732dc29cde0fdc7f64a9699d72a431416")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+f986e2387f42193e95687820c213e43880d84136")]
[assembly: System.Reflection.AssemblyProductAttribute("ShopAPI")]
[assembly: System.Reflection.AssemblyTitleAttribute("ShopAPI")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.
// Von der MSBuild WriteCodeFragment-Klasse generiert.

View File

@@ -1 +1 @@
8939993bdc8bf465475db388d074eb82a687860b9f0504b4815bf206f612de33
41098eb382a4f44343bd406c25389fc17c93ba3401bf7b32e24159269779bdd2

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"jjFS3ypc+SFFIJoabqxBcUwQp4+BH7vO9y9aDuWO8Ig=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["oM\u002B92zWtRWs1ZZHQG5F\u002BZt\u002BmUwKFCmEHXl6yhJyDB9E=","m4ORQ/F\u002BR\u002BZG7hKB0ZiSTgsXFT54fbrxurDLZfuPLtU=","/26wWziwS0KH/O896xGXBSLufvhay7wSjV2zdTxws18=","WyWGi43zm6PntQI/ucnnU3lxt5XudSMI/Un84LZNCNI=","pzhO73lOLr0aoNbQo3AXbJ7qsA2VDRY9Il7vtsfu6/g=","\u002BmYXsDWUwEv8MDDi5d\u002BdcyyfamgV9HnHNS18DvTVT8g=","KmtVrMRHetgVdPC7Ti0TzXPRMK5M58DycF9gOmYQmuk="],"CachedAssets":{},"CachedCopyCandidates":{}}
{"GlobalPropertiesHash":"jjFS3ypc+SFFIJoabqxBcUwQp4+BH7vO9y9aDuWO8Ig=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["oM\u002B92zWtRWs1ZZHQG5F\u002BZt\u002BmUwKFCmEHXl6yhJyDB9E=","m4ORQ/F\u002BR\u002BZG7hKB0ZiSTgsXFT54fbrxurDLZfuPLtU=","/26wWziwS0KH/O896xGXBSLufvhay7wSjV2zdTxws18=","WyWGi43zm6PntQI/ucnnU3lxt5XudSMI/Un84LZNCNI=","pzhO73lOLr0aoNbQo3AXbJ7qsA2VDRY9Il7vtsfu6/g=","\u002BmYXsDWUwEv8MDDi5d\u002BdcyyfamgV9HnHNS18DvTVT8g=","Tm7CcfRRz8vmlt8l9mYtBKdJqqgOF4FJyGXnX/H8m3Q="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"tbgf6NkZHDHq5Bwz13FNLNq2Biw7YSKbQETYkFTRirw=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["oM\u002B92zWtRWs1ZZHQG5F\u002BZt\u002BmUwKFCmEHXl6yhJyDB9E=","m4ORQ/F\u002BR\u002BZG7hKB0ZiSTgsXFT54fbrxurDLZfuPLtU=","/26wWziwS0KH/O896xGXBSLufvhay7wSjV2zdTxws18=","WyWGi43zm6PntQI/ucnnU3lxt5XudSMI/Un84LZNCNI=","pzhO73lOLr0aoNbQo3AXbJ7qsA2VDRY9Il7vtsfu6/g=","\u002BmYXsDWUwEv8MDDi5d\u002BdcyyfamgV9HnHNS18DvTVT8g=","KmtVrMRHetgVdPC7Ti0TzXPRMK5M58DycF9gOmYQmuk="],"CachedAssets":{},"CachedCopyCandidates":{}}
{"GlobalPropertiesHash":"tbgf6NkZHDHq5Bwz13FNLNq2Biw7YSKbQETYkFTRirw=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["oM\u002B92zWtRWs1ZZHQG5F\u002BZt\u002BmUwKFCmEHXl6yhJyDB9E=","m4ORQ/F\u002BR\u002BZG7hKB0ZiSTgsXFT54fbrxurDLZfuPLtU=","/26wWziwS0KH/O896xGXBSLufvhay7wSjV2zdTxws18=","WyWGi43zm6PntQI/ucnnU3lxt5XudSMI/Un84LZNCNI=","pzhO73lOLr0aoNbQo3AXbJ7qsA2VDRY9Il7vtsfu6/g=","\u002BmYXsDWUwEv8MDDi5d\u002BdcyyfamgV9HnHNS18DvTVT8g=","Tm7CcfRRz8vmlt8l9mYtBKdJqqgOF4FJyGXnX/H8m3Q="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -1,78 +1,612 @@
import type { AuthUser, Category, Order, Product } from "../types";
export const mockCategories: Category[] = [
{ id: 1, name: "Tech Essentials" },
{ id: 2, name: "Studio Setup" },
{ id: 3, name: "Smart Living" },
{ id: 4, name: "Travel Picks" }
];
const photo = (seed: string) => `https://picsum.photos/seed/${encodeURIComponent(seed)}/900/700`;
export const mockProducts: Product[] = [
export const mockCategories: Category[] = [
{
id: 1,
name: "Flux One Headphones",
description:
"Wireless over-ear headphones tuned for deep focus sessions, clear calls, and long battery life.",
price: 179.9,
stock: 14,
categoryId: 1,
image: "linear-gradient(135deg, #ff8a5b 0%, #ffd166 100%)",
featured: true
name: "Audio",
description: "Headphones, speakers, and all-day listening essentials.",
image: photo("fluxon-audio-category")
},
{
id: 2,
name: "Nova Desk Lamp",
description:
"A sculptural LED lamp with warm-to-cool temperature control for late-night work and clean desk aesthetics.",
price: 69,
stock: 22,
categoryId: 2,
image: "linear-gradient(135deg, #0f4c81 0%, #9bd1e5 100%)",
featured: true
name: "Smart Devices",
description: "Wearables and connected products for modern routines.",
image: photo("fluxon-smart-devices-category")
},
{
id: 3,
name: "Orbit Speaker Mini",
description:
"Portable speaker with punchy sound, matte finish, and enough battery to last through weekend trips.",
price: 95.5,
stock: 8,
categoryId: 4,
image: "linear-gradient(135deg, #23395d 0%, #b6c9f0 100%)",
featured: true
name: "Accessories",
description: "Chargers, stands, cables, and practical daily add-ons.",
image: photo("fluxon-accessories-category")
},
{
id: 4,
name: "Aero Bottle",
description:
"Insulated stainless steel bottle designed for city commutes, travel, and everyday carry.",
price: 32,
stock: 40,
categoryId: 4,
image: "linear-gradient(135deg, #2a6f97 0%, #61c0bf 100%)"
name: "Home Tech",
description: "Useful tech for comfort, lighting, cleaning, and air quality.",
image: photo("fluxon-home-tech-category")
},
{
id: 5,
name: "Canvas Keyboard",
description:
"Compact mechanical keyboard with low-profile switches and a clean, minimalist layout.",
price: 124,
stock: 16,
categoryId: 1,
image: "linear-gradient(135deg, #5f0f40 0%, #fb8b24 100%)"
},
{
id: 6,
name: "Pulse Air Purifier",
description:
"Smart purifier with quiet mode, room-quality indicator, and app-ready control concept.",
price: 210,
stock: 11,
categoryId: 3,
image: "linear-gradient(135deg, #355070 0%, #b56576 100%)"
name: "Personal Care",
description: "Smart grooming and self-care tools with a premium feel.",
image: photo("fluxon-personal-care-category")
}
];
type ProductSeed = Omit<Product, "id" | "categoryId" | "category"> & { categoryName: Category["name"] };
const productSeeds: ProductSeed[] = [
{
categoryName: "Audio",
name: "FluxBuds Air",
description: "True wireless earbuds with balanced sound and compact charging case.",
price: 69,
oldPrice: 89,
stock: 32,
badge: "New",
rating: 4.8,
reviewCount: 214,
featured: true,
newArrival: true,
image: photo("fluxon-audio-1")
},
{
categoryName: "Audio",
name: "NovaSound ANC",
description: "Over-ear headphones with active noise cancellation and 40-hour playback.",
price: 149,
oldPrice: 189,
stock: 18,
badge: "Best Seller",
rating: 4.9,
reviewCount: 843,
featured: true,
bestSeller: true,
image: photo("fluxon-audio-2")
},
{
categoryName: "Audio",
name: "PulseBeat Mini",
description: "Pocket speaker with rich bass tuning and splash-resistant finish.",
price: 54,
stock: 25,
badge: "Sale",
rating: 4.7,
reviewCount: 133,
image: photo("fluxon-audio-3")
},
{
categoryName: "Audio",
name: "WaveLoop Pro",
description: "Neckband earphones designed for calls, commuting, and long battery life.",
price: 39,
oldPrice: 49,
stock: 26,
rating: 4.6,
reviewCount: 91,
image: photo("fluxon-audio-4")
},
{
categoryName: "Audio",
name: "StudioArc Wired",
description: "Wired headphones with clean detail and lightweight studio-inspired design.",
price: 59,
stock: 21,
rating: 4.5,
reviewCount: 74,
image: photo("fluxon-audio-5")
},
{
categoryName: "Audio",
name: "GameTone X",
description: "Gaming headset with soft cushions, boom mic, and immersive stereo sound.",
price: 79,
oldPrice: 99,
stock: 17,
rating: 4.8,
reviewCount: 205,
image: photo("fluxon-audio-6")
},
{
categoryName: "Audio",
name: "RoomBar Slim",
description: "Minimal soundbar built for compact desks, bedrooms, and small TVs.",
price: 119,
stock: 10,
badge: "Hot",
rating: 4.7,
reviewCount: 168,
image: photo("fluxon-audio-7")
},
{
categoryName: "Audio",
name: "EchoDot Pocket",
description: "Mini speaker with soft-touch finish and quick-connect wireless pairing.",
price: 35,
stock: 40,
newArrival: true,
rating: 4.5,
reviewCount: 52,
image: photo("fluxon-audio-8")
},
{
categoryName: "Audio",
name: "QuietPods Max",
description: "Premium earbuds with deep ANC, transparency mode, and fast USB-C charging.",
price: 109,
oldPrice: 129,
stock: 15,
bestSeller: true,
rating: 4.9,
reviewCount: 479,
image: photo("fluxon-audio-9")
},
{
categoryName: "Audio",
name: "Reference One",
description: "Closed-back headphones for focused work, editing, and crisp detail.",
price: 129,
stock: 8,
rating: 4.8,
reviewCount: 118,
image: photo("fluxon-audio-10")
},
{
categoryName: "Smart Devices",
name: "Flux Watch S1",
description: "Smartwatch with AMOLED display, call support, and daily health tracking.",
price: 139,
oldPrice: 169,
stock: 22,
badge: "Best Seller",
rating: 4.9,
reviewCount: 692,
featured: true,
bestSeller: true,
image: photo("fluxon-smart-1")
},
{
categoryName: "Smart Devices",
name: "PulseBand Fit",
description: "Slim fitness band with sleep tracking, step count, and workout reminders.",
price: 49,
stock: 38,
rating: 4.6,
reviewCount: 175,
image: photo("fluxon-smart-2")
},
{
categoryName: "Smart Devices",
name: "Halo Ring Lite",
description: "Smart ring concept for sleep tracking and low-profile daily wear.",
price: 99,
oldPrice: 119,
stock: 11,
newArrival: true,
rating: 4.5,
reviewCount: 42,
image: photo("fluxon-smart-3")
},
{
categoryName: "Smart Devices",
name: "DeskHub Go",
description: "Compact smart desk hub with clock, USB ports, and workspace shortcuts.",
price: 89,
stock: 14,
rating: 4.4,
reviewCount: 36,
image: photo("fluxon-smart-4")
},
{
categoryName: "Smart Devices",
name: "WakeCube",
description: "Smart alarm clock with ambient light and gentle morning routines.",
price: 59,
stock: 29,
rating: 4.6,
reviewCount: 103,
image: photo("fluxon-smart-5")
},
{
categoryName: "Smart Devices",
name: "TrackTag Duo",
description: "Bluetooth tracker set for keys, backpacks, and travel essentials.",
price: 29,
oldPrice: 39,
stock: 47,
bestSeller: true,
rating: 4.8,
reviewCount: 318,
image: photo("fluxon-smart-6")
},
{
categoryName: "Smart Devices",
name: "Vista Mini",
description: "Portable smart display with clean interface for weather, timers, and media.",
price: 119,
stock: 9,
rating: 4.5,
reviewCount: 65,
image: photo("fluxon-smart-7")
},
{
categoryName: "Smart Devices",
name: "HealthSync Band",
description: "Daily wellness band focused on recovery insights and heart tracking.",
price: 65,
stock: 19,
rating: 4.6,
reviewCount: 98,
image: photo("fluxon-smart-8")
},
{
categoryName: "Smart Devices",
name: "Balance Scale Pro",
description: "Smart body scale with composition trends and companion-app readiness.",
price: 79,
stock: 13,
badge: "Popular",
rating: 4.7,
reviewCount: 151,
image: photo("fluxon-smart-9")
},
{
categoryName: "Smart Devices",
name: "Beam Pocket",
description: "Mini projector made for flexible movie nights and portable presentations.",
price: 199,
oldPrice: 239,
stock: 7,
newArrival: true,
rating: 4.7,
reviewCount: 87,
featured: true,
image: photo("fluxon-smart-10")
},
{
categoryName: "Accessories",
name: "VoltCharge 35",
description: "Fast wall charger with compact form and dual-device charging.",
price: 29,
stock: 56,
bestSeller: true,
rating: 4.8,
reviewCount: 521,
image: photo("fluxon-accessory-1")
},
{
categoryName: "Accessories",
name: "MagBank 10K",
description: "Magnetic power bank sized for travel days and fast top-ups.",
price: 69,
oldPrice: 89,
stock: 31,
badge: "Best Seller",
rating: 4.9,
reviewCount: 405,
featured: true,
bestSeller: true,
image: photo("fluxon-accessory-2")
},
{
categoryName: "Accessories",
name: "Braided Link C",
description: "Durable braided USB-C cable designed for desks, bags, and charging stations.",
price: 15,
stock: 82,
rating: 4.7,
reviewCount: 210,
image: photo("fluxon-accessory-3")
},
{
categoryName: "Accessories",
name: "AirDock Pad",
description: "Minimal wireless charging pad with soft LED ring and anti-slip base.",
price: 34,
stock: 28,
rating: 4.5,
reviewCount: 88,
image: photo("fluxon-accessory-4")
},
{
categoryName: "Accessories",
name: "Rise Laptop Stand",
description: "Foldable aluminum stand for cleaner posture and cooler laptop airflow.",
price: 42,
stock: 23,
rating: 4.8,
reviewCount: 144,
image: photo("fluxon-accessory-5")
},
{
categoryName: "Accessories",
name: "FlexGrip Holder",
description: "Adjustable phone holder for desks, kitchens, and bedside use.",
price: 19,
stock: 37,
rating: 4.4,
reviewCount: 61,
image: photo("fluxon-accessory-6")
},
{
categoryName: "Accessories",
name: "TravelPlug World",
description: "Travel adapter with clean design and multi-region compatibility.",
price: 39,
oldPrice: 49,
stock: 16,
newArrival: true,
rating: 4.6,
reviewCount: 57,
image: photo("fluxon-accessory-7")
},
{
categoryName: "Accessories",
name: "KeySleeve Pro",
description: "Protective keyboard sleeve with felt lining and slim profile.",
price: 24,
stock: 26,
rating: 4.5,
reviewCount: 41,
image: photo("fluxon-accessory-8")
},
{
categoryName: "Accessories",
name: "PortHub 6",
description: "Six-port USB hub for workstations that need flexible connectivity.",
price: 49,
stock: 21,
badge: "Hot",
rating: 4.7,
reviewCount: 129,
image: photo("fluxon-accessory-9")
},
{
categoryName: "Accessories",
name: "Shield Case Clear",
description: "Transparent protective phone case with reinforced corners.",
price: 18,
stock: 44,
newArrival: true,
rating: 4.3,
reviewCount: 39,
image: photo("fluxon-accessory-10")
},
{
categoryName: "Home Tech",
name: "PureFlow Air",
description: "Compact air purifier for bedrooms, workspaces, and quiet evenings.",
price: 189,
oldPrice: 229,
stock: 12,
featured: true,
badge: "Best Seller",
bestSeller: true,
rating: 4.9,
reviewCount: 366,
image: photo("fluxon-home-1")
},
{
categoryName: "Home Tech",
name: "Luma Desk Beam",
description: "LED desk lamp with adjustable warmth and a clean architectural silhouette.",
price: 64,
stock: 34,
rating: 4.8,
reviewCount: 202,
image: photo("fluxon-home-2")
},
{
categoryName: "Home Tech",
name: "SweepBot Mini",
description: "Robot vacuum built for daily dust pickup in compact living spaces.",
price: 249,
oldPrice: 299,
stock: 8,
rating: 4.7,
reviewCount: 157,
image: photo("fluxon-home-3")
},
{
categoryName: "Home Tech",
name: "MistCore",
description: "Quiet humidifier with soft light and modern bedside presence.",
price: 55,
stock: 20,
newArrival: true,
rating: 4.6,
reviewCount: 84,
image: photo("fluxon-home-4")
},
{
categoryName: "Home Tech",
name: "Aroma Glow",
description: "Aroma diffuser combining gentle vapor flow with ambient mood lighting.",
price: 39,
stock: 24,
rating: 4.5,
reviewCount: 72,
image: photo("fluxon-home-5")
},
{
categoryName: "Home Tech",
name: "CoolFold Fan",
description: "Portable fan with foldable body and desk-friendly footprint.",
price: 45,
stock: 30,
rating: 4.6,
reviewCount: 93,
image: photo("fluxon-home-6")
},
{
categoryName: "Home Tech",
name: "GlowBulb Kit",
description: "Smart bulb starter kit for mood shifts, desk scenes, and warm evenings.",
price: 79,
stock: 18,
badge: "Popular",
rating: 4.7,
reviewCount: 147,
image: photo("fluxon-home-7")
},
{
categoryName: "Home Tech",
name: "WarmSpace Mini",
description: "Compact heater designed for focused work corners and cool mornings.",
price: 99,
oldPrice: 119,
stock: 11,
rating: 4.4,
reviewCount: 48,
image: photo("fluxon-home-8")
},
{
categoryName: "Home Tech",
name: "ClearTap Filter",
description: "Countertop water filter unit with simple control and clean lines.",
price: 129,
stock: 9,
rating: 4.6,
reviewCount: 67,
image: photo("fluxon-home-9")
},
{
categoryName: "Home Tech",
name: "DustGo Handheld",
description: "Handheld mini vacuum for shelves, keyboards, and quick spot cleaning.",
price: 59,
stock: 27,
newArrival: true,
featured: true,
rating: 4.7,
reviewCount: 112,
image: photo("fluxon-home-10")
},
{
categoryName: "Personal Care",
name: "TrimEdge Pro",
description: "Cordless beard trimmer with precise guide combs and sharp stainless blades.",
price: 69,
oldPrice: 89,
stock: 22,
badge: "Best Seller",
featured: true,
bestSeller: true,
rating: 4.9,
reviewCount: 553,
image: photo("fluxon-care-1")
},
{
categoryName: "Personal Care",
name: "SilkDry Air",
description: "Hair dryer with sleek build, fast airflow, and low-frizz styling mode.",
price: 99,
stock: 19,
rating: 4.8,
reviewCount: 188,
image: photo("fluxon-care-2")
},
{
categoryName: "Personal Care",
name: "PureFace Brush",
description: "Facial cleansing brush for a softer skincare routine and clean countertop look.",
price: 34,
stock: 31,
rating: 4.5,
reviewCount: 77,
image: photo("fluxon-care-3")
},
{
categoryName: "Personal Care",
name: "BodyLine Groomer",
description: "Water-resistant body groomer built for comfortable weekly upkeep.",
price: 49,
stock: 25,
rating: 4.6,
reviewCount: 90,
image: photo("fluxon-care-4")
},
{
categoryName: "Personal Care",
name: "ReliefPulse Mini",
description: "Compact massage gun for post-workout recovery and daily neck tension relief.",
price: 119,
oldPrice: 149,
stock: 13,
bestSeller: true,
rating: 4.8,
reviewCount: 209,
image: photo("fluxon-care-5")
},
{
categoryName: "Personal Care",
name: "SmoothTouch Epilator",
description: "Epilator with travel cap, dual speeds, and ergonomic body shape.",
price: 79,
stock: 17,
newArrival: true,
rating: 4.5,
reviewCount: 58,
image: photo("fluxon-care-6")
},
{
categoryName: "Personal Care",
name: "BeardCare Kit",
description: "Premium beard kit with trimmer tools and simple daily maintenance feel.",
price: 59,
stock: 28,
rating: 4.7,
reviewCount: 101,
image: photo("fluxon-care-7")
},
{
categoryName: "Personal Care",
name: "SleekIron One",
description: "Hair straightener with smooth plates and salon-inspired matte finish.",
price: 69,
stock: 15,
rating: 4.6,
reviewCount: 69,
image: photo("fluxon-care-8")
},
{
categoryName: "Personal Care",
name: "SonicBrush Daily",
description: "Sonic toothbrush with travel case and two brushing intensity modes.",
price: 45,
stock: 33,
badge: "Popular",
rating: 4.7,
reviewCount: 142,
image: photo("fluxon-care-9")
},
{
categoryName: "Personal Care",
name: "NailStudio Go",
description: "Portable manicure device built for neat, at-home finishing touches.",
price: 29,
stock: 30,
newArrival: true,
featured: true,
rating: 4.4,
reviewCount: 33,
image: photo("fluxon-care-10")
}
];
export const mockProducts: Product[] = productSeeds.map((seed, index) => {
const category = mockCategories.find((item) => item.name === seed.categoryName)!;
return {
id: index + 1,
categoryId: category.id,
category,
...seed
};
});
export const mockDemoUser: AuthUser = {
name: "Demo Customer",
email: "demo@fluxon.shop",
@@ -87,21 +621,27 @@ export const mockOrders: Order[] = [
total: 248.9,
items: [
{
productId: 1,
productName: "Flux One Headphones",
productId: 2,
productName: "NovaSound ANC",
quantity: 1,
unitPrice: 179.9
unitPrice: 149
},
{
productId: 4,
productName: "Aero Bottle",
quantity: 2,
unitPrice: 32
productId: 21,
productName: "MagBank 10K",
quantity: 1,
unitPrice: 69
},
{
productId: 43,
productName: "ReliefPulse Mini",
quantity: 1,
unitPrice: 119
}
],
payment: {
method: "PayPal",
amount: 248.9,
amount: 337,
status: "Paid"
},
customerEmail: "demo@fluxon.shop",

View File

@@ -2,6 +2,7 @@ import { Link } from "react-router-dom";
import { useCart } from "../state/CartContext";
import { QuantityControl } from "../ui/QuantityControl";
import { StatusView } from "../ui/StatusView";
import { visualStyle } from "../ui/visuals";
export function CartPage() {
const { items, removeItem, updateQuantity, subtotal } = useCart();
@@ -33,7 +34,7 @@ export function CartPage() {
<div className="cart-list">
{items.map((item) => (
<article key={item.product.id} className="cart-row">
<div className="cart-visual" style={{ background: item.product.image }} />
<div className="cart-visual" style={visualStyle(item.product.image)} />
<div className="cart-copy">
<h3>{item.product.name}</h3>
<p>{item.product.description}</p>

View File

@@ -16,39 +16,41 @@ export function HomePage() {
return <StatusView title="Catalog unavailable" message={error} />;
}
const featuredProducts = products.filter((product) => product.featured).slice(0, 3);
const featuredProducts = products.filter((product) => product.featured).slice(0, 4);
const bestSellers = products.filter((product) => product.bestSeller).slice(0, 4);
const newArrivals = products.filter((product) => product.newArrival).slice(0, 4);
return (
<div className="page-stack">
<section className="hero-panel">
<div className="hero-copy">
<span className="eyebrow">Fluxon storefront</span>
<h1>Build a demo-ready shop now, then swap in real APIs as the backend catches up.</h1>
<span className="eyebrow">Next-Gen Everyday Tech</span>
<h1>Smart products built for modern daily life.</h1>
<p>
This frontend is structured for hybrid delivery: polished enough for presentation, flexible enough for
incomplete endpoints.
Discover a curated storefront across Audio, Smart Devices, Accessories, Home Tech, and Personal Care with
a presentation-ready shopping flow.
</p>
<div className="inline-actions">
<Link to="/products" className="cta-button">
Explore Products
Shop Now
</Link>
<Link to="/register" className="ghost-button">
Create Demo Account
<Link to="/products" className="ghost-button">
Explore Categories
</Link>
</div>
</div>
<div className="hero-card-grid">
<div className="hero-stat">
<strong>{products.length}</strong>
<span>Curated products</span>
<span>Store-ready products</span>
</div>
<div className="hero-stat">
<strong>{categories.length}</strong>
<span>Shop categories</span>
<span>Core categories</span>
</div>
<div className="hero-stat accent">
<strong>Mock + API</strong>
<span>Safe for evolving backend</span>
<strong>Deep Navy + Orange</strong>
<span>Clean tech-commerce direction</span>
</div>
</div>
</section>
@@ -57,14 +59,17 @@ export function HomePage() {
<div className="section-heading">
<div>
<span className="eyebrow">Categories</span>
<h2>Shape the browsing experience around the backend data model</h2>
<h2>Shop the five storefront pillars of Fluxon</h2>
</div>
</div>
<div className="category-grid">
{categories.map((category) => (
<article key={category.id} className="category-card">
<h3>{category.name}</h3>
<p>Use this category as a filter, navigation cue, and featured-content block.</p>
<p>{category.description}</p>
<Link to={`/products`} className="category-link">
Explore
</Link>
</article>
))}
</div>
@@ -74,7 +79,7 @@ export function HomePage() {
<div className="section-heading">
<div>
<span className="eyebrow">Featured</span>
<h2>Presentation-friendly products for your MVP demo flow</h2>
<h2>Featured picks for the homepage hero flow</h2>
</div>
<Link to="/products" className="ghost-button">
View All
@@ -86,6 +91,72 @@ export function HomePage() {
))}
</div>
</section>
<section className="promo-band">
<article className="promo-card">
<span className="eyebrow">Promo</span>
<h3>Up to 30% off selected Audio and Accessories</h3>
<p>Use this section for discounts, launches, or your strongest weekly campaign.</p>
<Link to="/products" className="ghost-button">
See Offers
</Link>
</article>
<article className="promo-card promo-card-dark">
<span className="eyebrow">New Drop</span>
<h3>Fresh Smart Devices and Personal Care arrivals</h3>
<p>Keep the homepage feeling alive with fast-moving campaign blocks like this one.</p>
<Link to="/products" className="cta-button">
Browse New Arrivals
</Link>
</article>
</section>
<section className="panel">
<div className="section-heading">
<div>
<span className="eyebrow">Best Sellers</span>
<h2>Products that add social proof to your storefront</h2>
</div>
</div>
<div className="product-grid">
{bestSellers.map((product) => (
<ProductCard key={product.id} product={product} onAdd={addItem} />
))}
</div>
</section>
<section className="panel">
<div className="section-heading">
<div>
<span className="eyebrow">New Arrivals</span>
<h2>Fresh additions to keep the shop feeling current</h2>
</div>
</div>
<div className="product-grid">
{newArrivals.map((product) => (
<ProductCard key={product.id} product={product} onAdd={addItem} />
))}
</div>
</section>
<section className="trust-grid">
<article className="trust-card">
<h3>Secure Checkout</h3>
<p>Use this block to reassure users that payments and account actions are protected.</p>
</article>
<article className="trust-card">
<h3>Fast Delivery</h3>
<p>Highlight delivery expectations and shipping confidence early in the homepage flow.</p>
</article>
<article className="trust-card">
<h3>Curated Products</h3>
<p>Show that Fluxon is not random inventory, but a selected modern tech catalog.</p>
</article>
<article className="trust-card">
<h3>Helpful Support</h3>
<p>Good support messaging makes a student project feel more like a real commerce brand.</p>
</article>
</section>
</div>
);
}

View File

@@ -5,6 +5,7 @@ import type { Product } from "../types";
import { StatusView } from "../ui/StatusView";
import { QuantityControl } from "../ui/QuantityControl";
import { useCart } from "../state/CartContext";
import { visualStyle } from "../ui/visuals";
export function ProductDetailsPage() {
const { productId } = useParams();
@@ -67,15 +68,22 @@ export function ProductDetailsPage() {
return (
<section className="product-detail-layout">
<div className="detail-visual" style={{ background: product.image }} />
<div className="detail-visual" style={visualStyle(product.image)} />
<div className="detail-copy panel">
<span className="eyebrow">{product.category?.name ?? "Product details"}</span>
<h1>{product.name}</h1>
<p className="lead">{product.description}</p>
<div className="rating-row">
<span>{product.rating ? `${product.rating.toFixed(1)} / 5` : "New item"}</span>
<span>{product.reviewCount ? `${product.reviewCount} verified reviews` : "Fresh listing"}</span>
</div>
<div className="detail-meta">
<div>
<span>Price</span>
<strong>EUR {product.price.toFixed(2)}</strong>
<div className="price-stack">
<strong>EUR {product.price.toFixed(2)}</strong>
{product.oldPrice ? <span>EUR {product.oldPrice.toFixed(2)}</span> : null}
</div>
</div>
<div>
<span>Availability</span>

View File

@@ -27,7 +27,13 @@ export function ProductsPage() {
);
}
switch (sort) {
switch (sort) {
case "new":
next.sort((a, b) => Number(b.newArrival) - Number(a.newArrival));
break;
case "best":
next.sort((a, b) => Number(b.bestSeller) - Number(a.bestSeller));
break;
case "price-asc":
next.sort((a, b) => a.price - b.price);
break;
@@ -72,6 +78,8 @@ export function ProductsPage() {
/>
<select value={sort} onChange={(event) => setSort(event.target.value)} className="select-input">
<option value="featured">Featured first</option>
<option value="best">Best sellers</option>
<option value="new">New arrivals</option>
<option value="price-asc">Price: low to high</option>
<option value="price-desc">Price: high to low</option>
<option value="stock">Most in stock</option>

View File

@@ -309,6 +309,13 @@ label {
margin: 0 0 0.35rem;
}
.category-link {
display: inline-flex;
margin-top: 0.75rem;
color: var(--accent-deep);
font-weight: 800;
}
.product-grid {
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
@@ -329,12 +336,51 @@ label {
min-height: 220px;
}
.product-visual {
position: relative;
}
.product-badge {
position: absolute;
top: 16px;
left: 16px;
padding: 0.45rem 0.75rem;
border-radius: 999px;
background: rgba(19, 34, 56, 0.88);
color: white;
font-size: 0.78rem;
font-weight: 800;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.product-copy {
display: grid;
gap: 0.8rem;
padding: 20px;
}
.rating-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
color: var(--ink-soft);
font-size: 0.86rem;
font-weight: 700;
}
.price-stack {
display: grid;
gap: 0.15rem;
}
.price-stack span {
color: var(--ink-soft);
font-size: 0.86rem;
text-decoration: line-through;
}
.chip,
.stock,
.category-pill {
@@ -510,6 +556,52 @@ label {
background: rgba(255, 255, 255, 0.6);
}
.promo-band,
.trust-grid {
display: grid;
gap: 18px;
}
.promo-band {
grid-template-columns: repeat(2, 1fr);
}
.promo-card,
.trust-card {
padding: 28px;
border: 1px solid var(--border);
border-radius: var(--radius-lg);
box-shadow: var(--shadow);
}
.promo-card {
background: linear-gradient(135deg, rgba(255, 122, 69, 0.12) 0%, rgba(255, 255, 255, 0.9) 100%);
}
.promo-card-dark {
color: white;
background: linear-gradient(135deg, #132238 0%, #20364f 100%);
}
.promo-card-dark p,
.promo-card-dark .eyebrow,
.promo-card-dark h3 {
color: rgba(255, 255, 255, 0.92);
}
.trust-grid {
grid-template-columns: repeat(4, 1fr);
}
.trust-card {
background: rgba(255, 255, 255, 0.78);
}
.trust-card h3 {
margin-top: 0;
margin-bottom: 0.5rem;
}
.footer-grid {
grid-template-columns: repeat(3, auto);
align-content: center;
@@ -519,6 +611,8 @@ label {
.hero-panel,
.product-detail-layout,
.checkout-layout,
.promo-band,
.trust-grid,
.site-footer {
grid-template-columns: 1fr;
}
@@ -573,6 +667,7 @@ label {
.section-heading,
.toolbar,
.product-actions,
.rating-row,
.meta-row,
.inline-actions,
.detail-meta,

View File

@@ -1,6 +1,8 @@
export type Category = {
id: number;
name: string;
description?: string;
image?: string;
};
export type Product = {
@@ -8,11 +10,17 @@ export type Product = {
name: string;
description: string;
price: number;
oldPrice?: number;
stock: number;
categoryId: number;
category?: Category;
image: string;
badge?: string;
rating?: number;
reviewCount?: number;
featured?: boolean;
bestSeller?: boolean;
newArrival?: boolean;
};
export type CartItem = {

View File

@@ -1,5 +1,6 @@
import { Link } from "react-router-dom";
import type { Product } from "../types";
import { visualStyle } from "./visuals";
type ProductCardProps = {
product: Product;
@@ -9,7 +10,9 @@ type ProductCardProps = {
export function ProductCard({ product, onAdd }: ProductCardProps) {
return (
<article className="product-card">
<div className="product-visual" style={{ background: product.image }} />
<div className="product-visual" style={visualStyle(product.image)}>
{product.badge ? <span className="product-badge">{product.badge}</span> : null}
</div>
<div className="product-copy">
<div className="meta-row">
<span className="chip">{product.category?.name ?? "Category"}</span>
@@ -19,8 +22,15 @@ export function ProductCard({ product, onAdd }: ProductCardProps) {
</div>
<h3>{product.name}</h3>
<p>{product.description}</p>
<div className="rating-row">
<span>{product.rating ? `${product.rating.toFixed(1)} / 5` : "New item"}</span>
<span>{product.reviewCount ? `${product.reviewCount} reviews` : "No reviews yet"}</span>
</div>
<div className="product-actions">
<strong>EUR {product.price.toFixed(2)}</strong>
<div className="price-stack">
<strong>EUR {product.price.toFixed(2)}</strong>
{product.oldPrice ? <span>EUR {product.oldPrice.toFixed(2)}</span> : null}
</div>
<div className="inline-actions">
<Link to={`/products/${product.id}`} className="ghost-button">
Details

View File

@@ -0,0 +1,12 @@
export function visualStyle(image: string) {
if (image.startsWith("http")) {
return {
backgroundImage: `linear-gradient(180deg, rgba(19, 34, 56, 0.08), rgba(19, 34, 56, 0.2)), url("${image}")`,
backgroundSize: "cover",
backgroundPosition: "center",
backgroundRepeat: "no-repeat"
} as const;
}
return { background: image } as const;
}

1
frontend/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />