Landing page good for mobiles
This commit is contained in:
@@ -8,7 +8,6 @@ namespace Imprink.WebApi.Controllers;
|
|||||||
public class SeedingController(Seeder seeder) : ControllerBase
|
public class SeedingController(Seeder seeder) : ControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public async Task<ActionResult<bool>> Seed()
|
public async Task<ActionResult<bool>> Seed()
|
||||||
{
|
{
|
||||||
await seeder.SeedAsync();
|
await seeder.SeedAsync();
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ public class Seeder(ApplicationDbContext context)
|
|||||||
private readonly string[] _textileImages =
|
private readonly string[] _textileImages =
|
||||||
[
|
[
|
||||||
"https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=500",
|
"https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=500",
|
||||||
"https://images.unsplash.com/photo-1583743814966-8936f37f4ad2?w=500",
|
|
||||||
"https://images.unsplash.com/photo-1571945153237-4929e783af4a?w=500",
|
"https://images.unsplash.com/photo-1571945153237-4929e783af4a?w=500",
|
||||||
"https://images.unsplash.com/photo-1618354691373-d851c5c3a990?w=500",
|
"https://images.unsplash.com/photo-1618354691373-d851c5c3a990?w=500",
|
||||||
"https://images.unsplash.com/photo-1576566588028-4147f3842f27?w=500"
|
"https://images.unsplash.com/photo-1576566588028-4147f3842f27?w=500"
|
||||||
@@ -29,14 +28,11 @@ public class Seeder(ApplicationDbContext context)
|
|||||||
[
|
[
|
||||||
"https://images.unsplash.com/photo-1586023492125-27b2c045efd7?w=500",
|
"https://images.unsplash.com/photo-1586023492125-27b2c045efd7?w=500",
|
||||||
"https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=500",
|
"https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=500",
|
||||||
"https://images.unsplash.com/photo-1544966503-7cc5ac882d2e?w=500",
|
|
||||||
"https://images.unsplash.com/photo-1553062407-98eeb64c6a62?w=500"
|
"https://images.unsplash.com/photo-1553062407-98eeb64c6a62?w=500"
|
||||||
];
|
];
|
||||||
|
|
||||||
private readonly string[] _paperImages =
|
private readonly string[] _paperImages =
|
||||||
[
|
[
|
||||||
"https://images.unsplash.com/photo-1586281010691-79ab3d0f2102?w=500",
|
|
||||||
"https://images.unsplash.com/photo-1594736797933-d0401ba2fe65?w=500",
|
|
||||||
"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500",
|
"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500",
|
||||||
"https://images.unsplash.com/photo-1584464491033-06628f3a6b7b?w=500"
|
"https://images.unsplash.com/photo-1584464491033-06628f3a6b7b?w=500"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -2,3 +2,4 @@
|
|||||||
const nextConfig = {}
|
const nextConfig = {}
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|
||||||
|
|||||||
144
webui/package-lock.json
generated
144
webui/package-lock.json
generated
@@ -21,10 +21,13 @@
|
|||||||
"@stripe/react-stripe-js": "^3.7.0",
|
"@stripe/react-stripe-js": "^3.7.0",
|
||||||
"@stripe/stripe-js": "^7.3.1",
|
"@stripe/stripe-js": "^7.3.1",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
|
"i18next": "^25.2.1",
|
||||||
"lucide-react": "^0.516.0",
|
"lucide-react": "^0.516.0",
|
||||||
"next": "15.3.3",
|
"next": "15.3.3",
|
||||||
|
"next-i18next": "^15.4.2",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0",
|
||||||
|
"react-i18next": "^15.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
@@ -1688,6 +1691,16 @@
|
|||||||
"tailwindcss": "4.1.8"
|
"tailwindcss": "4.1.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
|
||||||
|
"integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/parse-json": {
|
"node_modules/@types/parse-json": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||||
@@ -1705,7 +1718,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.7.tgz",
|
||||||
"integrity": "sha512-BnsPLV43ddr05N71gaGzyZ5hzkCmGwhMvYc8zmvI8Ci1bRkkDSzDDVfAXfN2tk748OwI7ediiPX6PfT9p0QGVg==",
|
"integrity": "sha512-BnsPLV43ddr05N71gaGzyZ5hzkCmGwhMvYc8zmvI8Ci1bRkkDSzDDVfAXfN2tk748OwI7ediiPX6PfT9p0QGVg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
@@ -1892,6 +1904,17 @@
|
|||||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/core-js": {
|
||||||
|
"version": "3.43.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.43.0.tgz",
|
||||||
|
"integrity": "sha512-N6wEbTTZSYOY2rYAn85CuvWWkCK6QweMn7/4Nr3w+gDBeBhk/x4EJeY6FPo4QzDoJZxVTv8U7CMvgWk6pOHHqA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/core-js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cosmiconfig": {
|
"node_modules/cosmiconfig": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
|
||||||
@@ -2239,6 +2262,52 @@
|
|||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/html-parse-stringify": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"void-elements": "3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/i18next": {
|
||||||
|
"version": "25.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.2.1.tgz",
|
||||||
|
"integrity": "sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com/i18next.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.27.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/i18next-fs-backend": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-3ZlhNoF9yxnM8pa8bWp5120/Ob6t4lVl1l/tbLmkml/ei3ud8IWySCHt2lrY5xWRlSU5D9IV2sm5bEbGuTqwTw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||||
@@ -2743,6 +2812,42 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/next-i18next": {
|
||||||
|
"version": "15.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-15.4.2.tgz",
|
||||||
|
"integrity": "sha512-zgRxWf7kdXtM686ecGIBQL+Bq0+DqAhRlasRZ3vVF0TmrNTWkVhs52n//oU3Fj5O7r/xOKkECDUwfOuXVwTK/g==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com/i18next.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.23.2",
|
||||||
|
"@types/hoist-non-react-statics": "^3.3.6",
|
||||||
|
"core-js": "^3",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"i18next-fs-backend": "^2.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"i18next": ">= 23.7.13",
|
||||||
|
"next": ">= 12.0.0",
|
||||||
|
"react": ">= 17.0.2",
|
||||||
|
"react-i18next": ">= 13.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/next/node_modules/postcss": {
|
"node_modules/next/node_modules/postcss": {
|
||||||
"version": "8.4.31",
|
"version": "8.4.31",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||||
@@ -2913,6 +3018,32 @@
|
|||||||
"react": "^19.1.0"
|
"react": "^19.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-i18next": {
|
||||||
|
"version": "15.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.5.3.tgz",
|
||||||
|
"integrity": "sha512-ypYmOKOnjqPEJZO4m1BI0kS8kWqkBNsKYyhVUfij0gvjy9xJNoG/VcGkxq5dRlVwzmrmY1BQMAmpbbUBLwC4Kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.27.6",
|
||||||
|
"html-parse-stringify": "^3.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"i18next": ">= 23.2.3",
|
||||||
|
"react": ">= 16.8.0",
|
||||||
|
"typescript": "^5"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "19.1.0",
|
"version": "19.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz",
|
||||||
@@ -3171,6 +3302,15 @@
|
|||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/void-elements": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||||
|
|||||||
@@ -22,10 +22,13 @@
|
|||||||
"@stripe/react-stripe-js": "^3.7.0",
|
"@stripe/react-stripe-js": "^3.7.0",
|
||||||
"@stripe/stripe-js": "^7.3.1",
|
"@stripe/stripe-js": "^7.3.1",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
|
"i18next": "^25.2.1",
|
||||||
"lucide-react": "^0.516.0",
|
"lucide-react": "^0.516.0",
|
||||||
"next": "15.3.3",
|
"next": "15.3.3",
|
||||||
|
"next-i18next": "^15.4.2",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0",
|
||||||
|
"react-i18next": "^15.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
|
|||||||
@@ -246,10 +246,10 @@ export const lightTheme = createTheme({
|
|||||||
MuiChip: {
|
MuiChip: {
|
||||||
styleOverrides: {
|
styleOverrides: {
|
||||||
root: {
|
root: {
|
||||||
background: 'rgba(99, 102, 241, 0.1)',
|
background: 'rgba(99, 102, 241, 0.7)',
|
||||||
border: '1px solid rgba(99, 102, 241, 0.2)',
|
border: '1px solid rgba(99, 102, 241, 0.2)',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
background: 'rgba(99, 102, 241, 0.2)',
|
background: 'rgba(99, 102, 241, 0.9)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
Alert
|
Alert
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { ShoppingCart, Palette, CreditCard, LocalShipping, CheckCircle } from '@mui/icons-material';
|
import { ShoppingCart, Palette, ImageOutlined, CreditCard, LocalShipping, CheckCircle } from '@mui/icons-material';
|
||||||
import clientApi from "@/lib/clientApi";
|
import clientApi from "@/lib/clientApi";
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
@@ -27,10 +27,9 @@ export default function HomePage() {
|
|||||||
try {
|
try {
|
||||||
const response = await clientApi.get('/products/', {
|
const response = await clientApi.get('/products/', {
|
||||||
params: {
|
params: {
|
||||||
PageSize: 6,
|
PageSize: 3,
|
||||||
PageNumber: 1,
|
PageNumber: 1,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
IsCustomizable: true,
|
|
||||||
SortBy: 'Price',
|
SortBy: 'Price',
|
||||||
SortDirection: 'DESC'
|
SortDirection: 'DESC'
|
||||||
}
|
}
|
||||||
@@ -49,61 +48,138 @@ export default function HomePage() {
|
|||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
|
number: 1,
|
||||||
label: 'Pick an Item',
|
label: 'Pick an Item',
|
||||||
description: 'Browse our collection of customizable products and select the perfect base for your design.',
|
description: 'Browse our extensive collection of customizable products and select the perfect base for your design. From premium t-shirts and hoodies to mugs, phone cases, and more - we have everything you need to bring your vision to life.',
|
||||||
icon: <ShoppingCart sx={{ fontSize: 40 }} />,
|
icon: <ShoppingCart sx={{ fontSize: 80 }} />,
|
||||||
color: '#1976d2'
|
details: 'Explore hundreds of high-quality products across multiple categories. Filter by material, size, color, and price to find exactly what you\'re looking for.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
number: 2,
|
||||||
label: 'Choose Variant',
|
label: 'Choose Variant',
|
||||||
description: 'Select size, color, and material options that match your preferences and needs.',
|
description: 'Select from available sizes, colors, and material options that match your preferences and needs. Each product comes with detailed specifications and sizing guides.',
|
||||||
icon: <Palette sx={{ fontSize: 40 }} />,
|
icon: <Palette sx={{ fontSize: 80 }} />,
|
||||||
color: '#9c27b0'
|
details: 'View real-time previews of different variants. Check material quality, durability ratings, and care instructions for each option.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
number: 3,
|
||||||
label: 'Customize with Images',
|
label: 'Customize with Images',
|
||||||
description: 'Upload your designs, add text, or use our design tools to create something unique.',
|
description: 'Upload your own designs, add custom text, or use our intuitive design tools to create something truly unique. Our editor supports various file formats and offers professional design features.',
|
||||||
icon: <Palette sx={{ fontSize: 40 }} />,
|
icon: <ImageOutlined sx={{ fontSize: 80 }} />,
|
||||||
color: '#f57c00'
|
details: 'Drag and drop images, adjust positioning, add filters, create text overlays, and preview your design in real-time on the selected product.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
number: 4,
|
||||||
label: 'Pay',
|
label: 'Pay',
|
||||||
description: 'Secure checkout with multiple payment options. Review your order before finalizing.',
|
description: 'Complete your order with our secure checkout process. We accept multiple payment methods and provide instant order confirmation with detailed receipts.',
|
||||||
icon: <CreditCard sx={{ fontSize: 40 }} />,
|
icon: <CreditCard sx={{ fontSize: 80 }} />,
|
||||||
color: '#388e3c'
|
details: 'Review your design, confirm quantities, apply discount codes, and choose from various secure payment options including cards, PayPal, and more.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
number: 5,
|
||||||
label: 'Wait for Order',
|
label: 'Wait for Order',
|
||||||
description: 'We\'ll print and ship your custom item. Track your order status in real-time.',
|
description: 'Sit back and relax while we handle the rest. Our professional printing team will carefully produce your custom item and ship it directly to your door.',
|
||||||
icon: <LocalShipping sx={{ fontSize: 40 }} />,
|
icon: <LocalShipping sx={{ fontSize: 80 }} />,
|
||||||
color: '#d32f2f'
|
details: 'Track your order status in real-time, from printing to packaging to shipping. Receive updates via email and SMS throughout the process.'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="lg" sx={{ py: 4 }}>
|
<Container maxWidth="lg" sx={{ py: 4 }}>
|
||||||
<Box sx={{ mb: 8, textAlign: 'center' }}>
|
<Grid container spacing={6} alignItems="center" sx={{ mb: 6, minHeight: '70vh' }}>
|
||||||
<Typography variant="h1" gutterBottom sx={{ fontWeight: 'bold', mb: 3 }}>
|
<Grid item xs={12} md={7}>
|
||||||
Custom Printing Made Simple
|
<Box sx={{ textAlign: { xs: 'center', md: 'left' } }}>
|
||||||
|
<Typography
|
||||||
|
variant="h1"
|
||||||
|
gutterBottom
|
||||||
|
sx={{
|
||||||
|
fontWeight: 'bold',
|
||||||
|
mb: 3,
|
||||||
|
fontSize: { xs: '2.5rem', md: '3.5rem', lg: '4rem' },
|
||||||
|
lineHeight: 1.2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Custom Printing<br />
|
||||||
|
<Box component="span" sx={{ color: 'primary.main' }}>Made Simple</Box>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="h5" color="text.secondary" sx={{ mb: 4, maxWidth: 800, mx: 'auto' }}>
|
<Typography
|
||||||
|
variant="h5"
|
||||||
|
color="text.secondary"
|
||||||
|
sx={{
|
||||||
|
mb: 4,
|
||||||
|
lineHeight: 1.6,
|
||||||
|
fontSize: { xs: '1.2rem', md: '1.4rem' }
|
||||||
|
}}
|
||||||
|
>
|
||||||
Transform your ideas into reality with our premium custom printing services.
|
Transform your ideas into reality with our premium custom printing services.
|
||||||
From t-shirts to mugs, we bring your designs to life with professional quality.
|
From t-shirts to mugs, we bring your designs to life with professional quality
|
||||||
|
and lightning-fast turnaround times.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{ display: 'flex', gap: 2, justifyContent: 'center', flexWrap: 'wrap' }}>
|
|
||||||
<Button variant="contained" size="large" sx={{ px: 4, py: 1.5 }}>
|
<Box sx={{ mb: 4 }}>
|
||||||
Start Customizing
|
<Grid container spacing={3}>
|
||||||
</Button>
|
<Grid item xs={12} sm={6}>
|
||||||
<Button variant="outlined" size="large" sx={{ px: 4, py: 1.5 }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||||
|
<CheckCircle sx={{ color: 'primary.main', mr: 2 }} />
|
||||||
|
<Typography variant="body1" fontWeight="medium">
|
||||||
|
Professional Quality Guaranteed
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||||
|
<CheckCircle sx={{ color: 'primary.main', mr: 2 }} />
|
||||||
|
<Typography variant="body1" fontWeight="medium">
|
||||||
|
Fast 24-48 Hour Turnaround
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||||
|
<CheckCircle sx={{ color: 'primary.main', mr: 2 }} />
|
||||||
|
<Typography variant="body1" fontWeight="medium">
|
||||||
|
Free Design Support
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||||
|
<CheckCircle sx={{ color: 'primary.main', mr: 2 }} />
|
||||||
|
<Typography variant="body1" fontWeight="medium">
|
||||||
|
100% Satisfaction Promise
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', gap: 2, justifyContent: { xs: 'center', md: 'flex-start' }, flexWrap: 'wrap', mb: 4 }}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="large"
|
||||||
|
sx={{ px: 5, py: 2, fontSize: '1.2rem' }}
|
||||||
|
>
|
||||||
View Gallery
|
View Gallery
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box sx={{ mb: 8 }}>
|
<Typography variant="body2" color="text.secondary">
|
||||||
<Typography variant="h2" gutterBottom sx={{ textAlign: 'center', mb: 6 }}>
|
⭐⭐⭐⭐⭐ Trusted by 10,000+ customers • 4.9/5 rating
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Box sx={{ mb: 12 }}>
|
||||||
|
<Box sx={{ mb: 6, textAlign: { xs: 'center', md: 'left' } }}>
|
||||||
|
<Typography variant="h2" gutterBottom sx={{ fontWeight: 'bold', mb: 2 }}>
|
||||||
Featured Products
|
Featured Products
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography variant="h6" color="text.secondary" sx={{ maxWidth: 600 }}>
|
||||||
|
Discover our most popular customizable products. Each item is carefully selected
|
||||||
|
for quality and perfect for personalization.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{loading && (
|
{loading && (
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}>
|
<Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}>
|
||||||
@@ -118,13 +194,19 @@ export default function HomePage() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{!loading && !error && (
|
{!loading && !error && (
|
||||||
<Grid container spacing={3} sx={{ justifyContent: 'center' }}>
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
gap: 3,
|
||||||
|
justifyContent: { xs: 'center', lg: 'flex-start' }
|
||||||
|
}}>
|
||||||
{products.map((product) => (
|
{products.map((product) => (
|
||||||
<Grid item key={product.id}>
|
|
||||||
<Card
|
<Card
|
||||||
|
key={product.id}
|
||||||
sx={{
|
sx={{
|
||||||
height: 380,
|
width: { xs: '100%', sm: 'calc(50% - 12px)', lg: 'calc(33.333% - 16px)' },
|
||||||
width: 300,
|
maxWidth: { xs: 400, sm: 350, lg: 370 },
|
||||||
|
height: { xs: 450, sm: 480, lg: 500 },
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
transition: 'transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out',
|
transition: 'transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out',
|
||||||
@@ -136,23 +218,27 @@ export default function HomePage() {
|
|||||||
>
|
>
|
||||||
<CardMedia
|
<CardMedia
|
||||||
component="img"
|
component="img"
|
||||||
height="180"
|
height="200"
|
||||||
image={product.imageUrl || '/placeholder-product.jpg'}
|
image={product.imageUrl || '/placeholder-product.jpg'}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
sx={{ objectFit: 'cover' }}
|
sx={{
|
||||||
|
objectFit: 'cover',
|
||||||
|
height: { xs: 180, sm: 200, lg: 220 }
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<CardContent sx={{
|
<CardContent sx={{
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
p: 2,
|
p: { xs: 2, sm: 2.5, lg: 3 },
|
||||||
'&:last-child': { pb: 2 }
|
'&:last-child': { pb: { xs: 2, sm: 2.5, lg: 3 } }
|
||||||
}}>
|
}}>
|
||||||
<Typography variant="h6" gutterBottom sx={{
|
<Typography variant="h6" gutterBottom sx={{
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
whiteSpace: 'nowrap'
|
whiteSpace: 'nowrap',
|
||||||
|
fontSize: { xs: '1.1rem', sm: '1.25rem' }
|
||||||
}}>
|
}}>
|
||||||
{product.name}
|
{product.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -161,14 +247,18 @@ export default function HomePage() {
|
|||||||
mb: 2,
|
mb: 2,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
display: '-webkit-box',
|
display: '-webkit-box',
|
||||||
WebkitLineClamp: 2,
|
WebkitLineClamp: { xs: 2, sm: 3 },
|
||||||
WebkitBoxOrient: 'vertical',
|
WebkitBoxOrient: 'vertical',
|
||||||
minHeight: 40
|
minHeight: { xs: 36, sm: 54 },
|
||||||
|
fontSize: { xs: '0.875rem', sm: '0.875rem' }
|
||||||
}}>
|
}}>
|
||||||
{product.description}
|
{product.description}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }}>
|
||||||
<Typography variant="subtitle1" color="primary" sx={{ fontWeight: 'bold' }}>
|
<Typography variant="subtitle1" color="primary" sx={{
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: { xs: '1rem', sm: '1.1rem' }
|
||||||
|
}}>
|
||||||
From ${product.basePrice?.toFixed(2)}
|
From ${product.basePrice?.toFixed(2)}
|
||||||
</Typography>
|
</Typography>
|
||||||
{product.isCustomizable && (
|
{product.isCustomizable && (
|
||||||
@@ -182,72 +272,138 @@ export default function HomePage() {
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
fullWidth
|
fullWidth
|
||||||
size="small"
|
size="medium"
|
||||||
|
sx={{
|
||||||
|
fontSize: { xs: '0.875rem', sm: '1rem' },
|
||||||
|
py: { xs: 1, sm: 1.5 }
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Customize
|
Customize
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ mb: 12, py: 8 }}>
|
||||||
|
<Container maxWidth="lg">
|
||||||
<Box sx={{ mb: 8 }}>
|
<Box sx={{ mb: 8 }}>
|
||||||
<Typography variant="h2" gutterBottom sx={{ textAlign: 'center', mb: 6 }}>
|
<Typography variant="h2" gutterBottom sx={{ fontWeight: 'bold', mb: 2 }}>
|
||||||
How It Works
|
How It Works
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography variant="h5" color="text.secondary" sx={{ maxWidth: 600 }}>
|
||||||
|
Our streamlined process makes custom printing simple and stress-free.
|
||||||
|
Follow these five easy steps to get your perfect custom products.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ maxWidth: 800, mx: 'auto' }}>
|
<Grid container spacing={6}>
|
||||||
{steps.map((step, index) => (
|
{steps.map((step, index) => (
|
||||||
<Box key={index} sx={{ display: 'flex', mb: 4, position: 'relative' }}>
|
<Grid item xs={12} key={index}>
|
||||||
{index < steps.length - 1 && (
|
<Card
|
||||||
|
sx={{
|
||||||
|
p: 4,
|
||||||
|
boxShadow: 2,
|
||||||
|
borderRadius: 3,
|
||||||
|
transition: 'all 0.3s ease',
|
||||||
|
'&:hover': {
|
||||||
|
boxShadow: 8,
|
||||||
|
transform: 'translateY(-4px)'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid container spacing={4} alignItems="center">
|
||||||
|
<Grid item xs={12} md={2}>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
display: 'flex',
|
||||||
left: 30,
|
alignItems: 'center',
|
||||||
top: 80,
|
justifyContent: { xs: 'center', md: 'flex-start' },
|
||||||
width: 2,
|
mb: { xs: 2, md: 0 }
|
||||||
height: 60,
|
|
||||||
bgcolor: 'divider',
|
|
||||||
zIndex: 0
|
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
)}
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
borderRadius: 2,
|
||||||
|
bgcolor: 'primary.main',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
color: 'white',
|
||||||
|
mr: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{step.icon}
|
||||||
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: 60,
|
width: 60,
|
||||||
height: 60,
|
height: 60,
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
bgcolor: step.color,
|
bgcolor: 'primary.main',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
mr: 3,
|
color: 'white',
|
||||||
position: 'relative',
|
fontSize: '1.5rem',
|
||||||
zIndex: 1,
|
fontWeight: 'bold'
|
||||||
color: 'white'
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{step.icon}
|
{step.number}
|
||||||
</Box>
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Box sx={{ flex: 1, pt: 1 }}>
|
<Grid item xs={12} md={10}>
|
||||||
<Typography variant="h4" gutterBottom sx={{ fontWeight: 'bold', color: step.color }}>
|
<Box sx={{ textAlign: { xs: 'center', md: 'left' } }}>
|
||||||
{index + 1}. {step.label}
|
<Typography
|
||||||
|
variant="h4"
|
||||||
|
gutterBottom
|
||||||
|
sx={{
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: 'primary.main',
|
||||||
|
mb: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{step.label}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" color="text.secondary" sx={{ fontSize: '1.1rem' }}>
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
paragraph
|
||||||
|
sx={{
|
||||||
|
mb: 3,
|
||||||
|
lineHeight: 1.6,
|
||||||
|
color: 'text.primary',
|
||||||
|
fontWeight: 400
|
||||||
|
}}
|
||||||
|
>
|
||||||
{step.description}
|
{step.description}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
color="text.secondary"
|
||||||
|
sx={{
|
||||||
|
lineHeight: 1.7,
|
||||||
|
fontSize: '1.1rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{step.details}
|
||||||
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Grid>
|
||||||
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ textAlign: 'center', py: 6, bgcolor: 'background.paper', borderRadius: 2 }}>
|
<Box sx={{ textAlign: 'center', py: 8, bgcolor: 'background.paper', borderRadius: 2, boxShadow: 1 }}>
|
||||||
<Typography variant="h3" gutterBottom sx={{ fontWeight: 'bold', mb: 3 }}>
|
<Typography variant="h3" gutterBottom sx={{ fontWeight: 'bold', mb: 3 }}>
|
||||||
Ready to Get Started?
|
Ready to Get Started?
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
Reference in New Issue
Block a user