Compare commits
9 Commits
87db7ba3ea
...
live
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9df5642a6e | ||
|
|
a50dd086c3 | ||
|
|
e88370ff3e | ||
|
|
5d3e0832fe | ||
|
|
3347ba2754 | ||
|
|
013a38ca98 | ||
|
|
2d6c8ff25f | ||
|
|
d2ac8d3fc1 | ||
|
|
8928b3f283 |
154
docs/nginx.conf
Normal file
154
docs/nginx.conf
Normal file
@@ -0,0 +1,154 @@
|
||||
server {
|
||||
client_max_body_size 64M;
|
||||
listen 443 ssl;
|
||||
http2 on;
|
||||
server_name example.de;
|
||||
ssl_certificate /etc/letsencrypt/live/example.de/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/example.de/privkey.pem;
|
||||
|
||||
gzip on;
|
||||
gzip_comp_level 6;
|
||||
gzip_min_length 256;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_types
|
||||
text/css
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/x-javascript
|
||||
application/json
|
||||
application/xml
|
||||
image/svg+xml;
|
||||
|
||||
index index.html;
|
||||
root /example/dist;
|
||||
|
||||
error_log logs/error.log info;
|
||||
access_log logs/access.log combined;
|
||||
|
||||
location /socket.io/ {
|
||||
proxy_pass http://localhost:9303/socket.io/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
|
||||
proxy_connect_timeout 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_read_timeout 3600s;
|
||||
send_timeout 3600s;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
|
||||
keepalive_timeout 65;
|
||||
keepalive_requests 100;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://localhost:9303/api/;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_set_header User-Agent $http_user_agent;
|
||||
proxy_set_header Content-Type $content_type;
|
||||
proxy_set_header Content-Length $content_length;
|
||||
|
||||
proxy_set_header X-API-Key $http_x_api_key;
|
||||
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
proxy_buffering off;
|
||||
|
||||
client_max_body_size 10M;
|
||||
}
|
||||
|
||||
location ^~ /Kategorie/ {
|
||||
types {}
|
||||
default_type text/html;
|
||||
}
|
||||
|
||||
location ^~ /Artikel/ {
|
||||
types {}
|
||||
default_type text/html;
|
||||
}
|
||||
|
||||
location = /sitemap.xml {
|
||||
types {}
|
||||
default_type application/xml;
|
||||
}
|
||||
|
||||
location ~ ^/(datenschutz|impressum|batteriegesetzhinweise|widerrufsrecht|sitemap|agb|Kategorien|Konfigurator|404|profile|resetPassword|thc-test|filiale|aktionen|presseverleih|payment/success)(/|$) {
|
||||
types {}
|
||||
default_type text/html;
|
||||
}
|
||||
|
||||
location = /404 {
|
||||
error_page 404 =404 /404-big.html;
|
||||
return 404;
|
||||
}
|
||||
|
||||
location = /404-big.html {
|
||||
internal;
|
||||
alias /home/seb/src/growheads_de/dist/404;
|
||||
default_type text/html;
|
||||
}
|
||||
|
||||
error_page 404 /404.html;
|
||||
|
||||
location = /404.html {
|
||||
internal;
|
||||
default_type text/html;
|
||||
return 404 '<!doctype html><html><body>
|
||||
<script>
|
||||
if (!navigator.userAgent.includes("bot")) { location.href="/404"; }
|
||||
</script>
|
||||
</body></html>';
|
||||
}
|
||||
|
||||
location ~* \.(js|css)\?.*$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
add_header Vary Accept-Encoding;
|
||||
}
|
||||
|
||||
location ~* \.(js|css)$ {
|
||||
if ($uri ~ "\.[a-f0-9]{7,}\.(js|css)$") {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
break;
|
||||
}
|
||||
expires 1d;
|
||||
add_header Cache-Control "public";
|
||||
add_header Vary Accept-Encoding;
|
||||
}
|
||||
|
||||
location ~* \.(ttf|otf|woff|woff2|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public";
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
}
|
||||
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public";
|
||||
add_header Vary Accept-Encoding;
|
||||
}
|
||||
|
||||
location = /prerender.css {
|
||||
expires 1w;
|
||||
add_header Cache-Control "public";
|
||||
add_header Vary Accept-Encoding;
|
||||
}
|
||||
|
||||
location /assets/ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public";
|
||||
add_header Vary Accept-Encoding;
|
||||
}
|
||||
}
|
||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -4554,9 +4554,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001727",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
|
||||
"integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
|
||||
"version": "1.0.30001757",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz",
|
||||
"integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
||||
109
prerender.cjs
109
prerender.cjs
@@ -28,7 +28,7 @@ class CategoryService {
|
||||
const cacheKey = `${categoryId}_${language}`;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
async get(categoryId, language = "de") {
|
||||
const cacheKey = `${categoryId}_${language}`;
|
||||
return null;
|
||||
@@ -159,6 +159,7 @@ const Batteriegesetzhinweise =
|
||||
const Widerrufsrecht = require("./src/pages/Widerrufsrecht.js").default;
|
||||
const Sitemap = require("./src/pages/Sitemap.js").default;
|
||||
const PrerenderSitemap = require("./src/PrerenderSitemap.js").default;
|
||||
const PrerenderCategoriesPage = require("./src/PrerenderCategoriesPage.js").default;
|
||||
const AGB = require("./src/pages/AGB.js").default;
|
||||
const NotFound404 = require("./src/pages/NotFound404.js").default;
|
||||
|
||||
@@ -189,7 +190,7 @@ const renderProductWorker = async (productSeoNames, workerId, progressCallback,
|
||||
|
||||
try {
|
||||
const productDetails = await fetchProductDetails(workerSocket, productSeoName);
|
||||
|
||||
|
||||
const actualSeoName = productDetails.product.seoName || productSeoName;
|
||||
const productComponent = React.createElement(PrerenderProduct, {
|
||||
productData: productDetails,
|
||||
@@ -205,7 +206,7 @@ const renderProductWorker = async (productSeoNames, workerId, progressCallback,
|
||||
}, shopConfig.baseUrl, shopConfig);
|
||||
// Get category info from categoryMap if available
|
||||
const categoryInfo = productDetails.product.categoryId ? categoryMap[productDetails.product.categoryId] : null;
|
||||
|
||||
|
||||
const jsonLdScript = generateProductJsonLd({
|
||||
...productDetails.product,
|
||||
seoName: actualSeoName,
|
||||
@@ -234,9 +235,9 @@ const renderProductWorker = async (productSeoNames, workerId, progressCallback,
|
||||
success,
|
||||
workerId
|
||||
};
|
||||
|
||||
|
||||
results.push(result);
|
||||
|
||||
|
||||
// Call progress callback if provided
|
||||
if (progressCallback) {
|
||||
progressCallback(result);
|
||||
@@ -252,14 +253,14 @@ const renderProductWorker = async (productSeoNames, workerId, progressCallback,
|
||||
error: error.message,
|
||||
workerId
|
||||
};
|
||||
|
||||
|
||||
results.push(result);
|
||||
|
||||
|
||||
// Call progress callback if provided
|
||||
if (progressCallback) {
|
||||
progressCallback(result);
|
||||
}
|
||||
|
||||
|
||||
setTimeout(processNextProduct, 25);
|
||||
}
|
||||
};
|
||||
@@ -291,16 +292,16 @@ const renderProductsInParallel = async (allProductsArray, maxWorkers, totalProdu
|
||||
const barLength = 30;
|
||||
const filledLength = Math.round((barLength * current) / total);
|
||||
const bar = '█'.repeat(filledLength) + '░'.repeat(barLength - filledLength);
|
||||
|
||||
|
||||
// @note Single line progress update to prevent flickering
|
||||
const truncatedName = productName ? ` - ${productName.substring(0, 25)}${productName.length > 25 ? '...' : ''}` : '';
|
||||
|
||||
|
||||
// Build worker stats on one line
|
||||
let workerStats = '';
|
||||
for (let i = 0; i < Math.min(maxWorkers, 8); i++) { // Limit to 8 workers to fit on screen
|
||||
workerStats += `W${i + 1}:${workerCounts[i]}/${workerSuccess[i]} `;
|
||||
}
|
||||
|
||||
|
||||
// Single line update without complex cursor movements
|
||||
process.stdout.write(`\r [${bar}] ${percentage}% (${current}/${total})${truncatedName}\n ${workerStats}${current < total ? '\x1b[1A' : '\n'}`);
|
||||
};
|
||||
@@ -308,26 +309,26 @@ const renderProductsInParallel = async (allProductsArray, maxWorkers, totalProdu
|
||||
// Split products among workers
|
||||
const productsPerWorker = Math.ceil(allProductsArray.length / maxWorkers);
|
||||
const workerPromises = [];
|
||||
|
||||
|
||||
// Initial progress bar
|
||||
updateProgressBar(0, totalProducts);
|
||||
|
||||
|
||||
for (let i = 0; i < maxWorkers; i++) {
|
||||
const start = i * productsPerWorker;
|
||||
const end = Math.min(start + productsPerWorker, allProductsArray.length);
|
||||
const productsForWorker = allProductsArray.slice(start, end);
|
||||
|
||||
|
||||
if (productsForWorker.length > 0) {
|
||||
const promise = renderProductWorker(productsForWorker, i + 1, (result) => {
|
||||
// Progress callback - called each time a product is completed
|
||||
completedProducts++;
|
||||
progressResults.push(result);
|
||||
lastProductName = result.productName;
|
||||
|
||||
|
||||
// Update per-worker counters
|
||||
const workerIndex = result.workerId - 1; // Convert to 0-based index
|
||||
workerCounts[workerIndex]++;
|
||||
|
||||
|
||||
if (result.success) {
|
||||
totalSuccessCount++;
|
||||
workerSuccess[workerIndex]++;
|
||||
@@ -335,11 +336,11 @@ const renderProductsInParallel = async (allProductsArray, maxWorkers, totalProdu
|
||||
// Don't log errors immediately to avoid interfering with progress bar
|
||||
// Errors will be shown after completion
|
||||
}
|
||||
|
||||
|
||||
// Update progress bar with worker stats
|
||||
updateProgressBar(completedProducts, totalProducts, lastProductName);
|
||||
}, categoryMap);
|
||||
|
||||
|
||||
workerPromises.push(promise);
|
||||
}
|
||||
}
|
||||
@@ -347,10 +348,10 @@ const renderProductsInParallel = async (allProductsArray, maxWorkers, totalProdu
|
||||
try {
|
||||
// Wait for all workers to complete
|
||||
await Promise.all(workerPromises);
|
||||
|
||||
|
||||
// Ensure final progress update
|
||||
updateProgressBar(totalProducts, totalProducts, lastProductName);
|
||||
|
||||
|
||||
// Show any errors that occurred
|
||||
const errorResults = progressResults.filter(r => !r.success && r.error);
|
||||
if (errorResults.length > 0) {
|
||||
@@ -359,7 +360,7 @@ const renderProductsInParallel = async (allProductsArray, maxWorkers, totalProdu
|
||||
console.log(` - ${result.productSeoName}: ${result.error}`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return totalSuccessCount;
|
||||
} catch (error) {
|
||||
console.error('Error in parallel rendering:', error);
|
||||
@@ -422,6 +423,14 @@ const renderApp = async (categoryData, socket) => {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Copy index.html to resetPassword (no file extension) for SPA routing
|
||||
if (config.isProduction) {
|
||||
const indexPath = path.resolve(__dirname, config.outputDir, "index.html");
|
||||
const resetPasswordPath = path.resolve(__dirname, config.outputDir, "resetPassword");
|
||||
fs.copyFileSync(indexPath, resetPasswordPath);
|
||||
console.log(`✅ Copied index.html to ${resetPasswordPath}`);
|
||||
}
|
||||
|
||||
// Render static pages
|
||||
console.log("\n📄 Rendering static pages...");
|
||||
|
||||
@@ -457,6 +466,13 @@ const renderApp = async (categoryData, socket) => {
|
||||
description: "Sitemap page",
|
||||
needsCategoryData: true,
|
||||
},
|
||||
{
|
||||
component: PrerenderCategoriesPage,
|
||||
path: "/Kategorien",
|
||||
filename: "Kategorien",
|
||||
description: "Categories page",
|
||||
needsCategoryData: true,
|
||||
},
|
||||
{ component: AGB, path: "/agb", filename: "agb", description: "AGB page" },
|
||||
{ component: NotFound404, path: "/404", filename: "404", description: "404 Not Found page" },
|
||||
{
|
||||
@@ -551,8 +567,7 @@ const renderApp = async (categoryData, socket) => {
|
||||
try {
|
||||
productData = await fetchCategoryProducts(socket, category.id);
|
||||
console.log(
|
||||
` ✅ Found ${
|
||||
productData.products ? productData.products.length : 0
|
||||
` ✅ Found ${productData.products ? productData.products.length : 0
|
||||
} products`
|
||||
);
|
||||
|
||||
@@ -636,7 +651,7 @@ const renderApp = async (categoryData, socket) => {
|
||||
const totalProducts = allProducts.size;
|
||||
const numCPUs = os.cpus().length;
|
||||
const maxWorkers = Math.min(numCPUs, totalProducts, 8); // Cap at 8 workers to avoid overwhelming the server
|
||||
|
||||
|
||||
// Create category map for breadcrumbs
|
||||
const categoryMap = {};
|
||||
allCategories.forEach(category => {
|
||||
@@ -645,11 +660,11 @@ const renderApp = async (categoryData, socket) => {
|
||||
seoName: category.seoName
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
console.log(
|
||||
`\n📦 Rendering ${totalProducts} individual product pages using ${maxWorkers} parallel workers...`
|
||||
);
|
||||
|
||||
|
||||
const productPagesRendered = await renderProductsInParallel(
|
||||
Array.from(allProducts),
|
||||
maxWorkers,
|
||||
@@ -701,21 +716,21 @@ const renderApp = async (categoryData, socket) => {
|
||||
// Generate products.xml (Google Shopping feed) in parallel to sitemap.xml
|
||||
if (allProductsData.length > 0) {
|
||||
console.log("\n🛒 Generating products.xml (Google Shopping feed)...");
|
||||
|
||||
|
||||
try {
|
||||
const productsXml = generateProductsXml(allProductsData, shopConfig.baseUrl, shopConfig);
|
||||
|
||||
|
||||
const productsXmlPath = path.resolve(__dirname, config.outputDir, "products.xml");
|
||||
|
||||
|
||||
// Write with explicit UTF-8 encoding
|
||||
fs.writeFileSync(productsXmlPath, productsXml, { encoding: 'utf8' });
|
||||
|
||||
|
||||
console.log(`✅ products.xml generated: ${productsXmlPath}`);
|
||||
console.log(` - Products included: ${allProductsData.length}`);
|
||||
console.log(` - Format: Google Shopping RSS 2.0 feed`);
|
||||
console.log(` - Encoding: UTF-8`);
|
||||
console.log(` - Includes: title, description, price, availability, images`);
|
||||
|
||||
|
||||
// Verify the file is valid UTF-8
|
||||
try {
|
||||
const verification = fs.readFileSync(productsXmlPath, 'utf8');
|
||||
@@ -723,18 +738,18 @@ const renderApp = async (categoryData, socket) => {
|
||||
} catch (verifyError) {
|
||||
console.log(` - File verification: ⚠️ ${verifyError.message}`);
|
||||
}
|
||||
|
||||
|
||||
// Validate XML against Google Shopping schema
|
||||
try {
|
||||
const ProductsXmlValidator = require('./scripts/validate-products-xml.cjs');
|
||||
const validator = new ProductsXmlValidator(productsXmlPath);
|
||||
const validationResults = await validator.validate();
|
||||
|
||||
|
||||
if (validationResults.valid) {
|
||||
console.log(` - Schema validation: ✅ Valid Google Shopping RSS 2.0`);
|
||||
} else {
|
||||
console.log(` - Schema validation: ⚠️ ${validationResults.summary.errorCount} errors, ${validationResults.summary.warningCount} warnings`);
|
||||
|
||||
|
||||
// Show first few errors for quick debugging
|
||||
if (validationResults.errors.length > 0) {
|
||||
console.log(` - First error: ${validationResults.errors[0].message}`);
|
||||
@@ -743,7 +758,7 @@ const renderApp = async (categoryData, socket) => {
|
||||
} catch (validationError) {
|
||||
console.log(` - Schema validation: ⚠️ Validation failed: ${validationError.message}`);
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Error generating products.xml: ${error.message}`);
|
||||
console.log("\n⚠️ Skipping products.xml generation due to errors");
|
||||
@@ -754,18 +769,18 @@ const renderApp = async (categoryData, socket) => {
|
||||
|
||||
// Generate llms.txt (LLM-friendly markdown sitemap) and category-specific files
|
||||
console.log("\n🤖 Generating LLM sitemap files...");
|
||||
|
||||
|
||||
try {
|
||||
// Generate main llms.txt overview file
|
||||
const llmsTxt = generateLlmsTxt(allCategories, allProductsData, shopConfig.baseUrl, shopConfig);
|
||||
const llmsTxtPath = path.resolve(__dirname, config.outputDir, "llms.txt");
|
||||
fs.writeFileSync(llmsTxtPath, llmsTxt, { encoding: 'utf8' });
|
||||
|
||||
|
||||
console.log(`✅ Main llms.txt generated: ${llmsTxtPath}`);
|
||||
console.log(` - Static pages: 8 pages`);
|
||||
console.log(` - Categories: ${allCategories.length} with links to detailed files`);
|
||||
console.log(` - File size: ${Math.round(llmsTxt.length / 1024)}KB`);
|
||||
|
||||
|
||||
// Group products by category for category-specific files
|
||||
const productsByCategory = {};
|
||||
allProductsData.forEach((product) => {
|
||||
@@ -775,20 +790,20 @@ const renderApp = async (categoryData, socket) => {
|
||||
}
|
||||
productsByCategory[categoryId].push(product);
|
||||
});
|
||||
|
||||
|
||||
// Generate category-specific LLM files with pagination
|
||||
let categoryFilesGenerated = 0;
|
||||
let totalCategoryProducts = 0;
|
||||
let totalPaginatedFiles = 0;
|
||||
|
||||
|
||||
for (const category of allCategories) {
|
||||
if (category.seoName) {
|
||||
const categoryProducts = productsByCategory[category.id] || [];
|
||||
const categorySlug = category.seoName.toLowerCase().replace(/[^a-z0-9]/g, '-');
|
||||
|
||||
|
||||
// Generate all paginated files for this category
|
||||
const categoryPages = generateAllCategoryLlmsPages(category, categoryProducts, shopConfig.baseUrl, shopConfig);
|
||||
|
||||
|
||||
// Write each paginated file
|
||||
for (const page of categoryPages) {
|
||||
const pagePath = path.resolve(__dirname, config.outputDir, page.fileName);
|
||||
@@ -806,22 +821,22 @@ const renderApp = async (categoryData, socket) => {
|
||||
|
||||
console.log(` ✅ llms-${categorySlug}-page-*.txt - ${categoryProducts.length} products across ${pageCount} pages (${Math.round(totalSize / 1024)}KB total)`);
|
||||
console.log(` 📋 ${productList.fileName} - ${productList.productCount} products (${Math.round(productList.content.length / 1024)}KB)`);
|
||||
|
||||
|
||||
categoryFilesGenerated++;
|
||||
totalCategoryProducts += categoryProducts.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
console.log(` 📄 Total paginated files generated: ${totalPaginatedFiles}`);
|
||||
console.log(` 📦 Total products across all categories: ${totalCategoryProducts}`);
|
||||
|
||||
|
||||
try {
|
||||
const verification = fs.readFileSync(llmsTxtPath, 'utf8');
|
||||
console.log(` - File verification: ✅ All files valid UTF-8`);
|
||||
} catch (verifyError) {
|
||||
console.log(` - File verification: ⚠️ ${verifyError.message}`);
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Error generating LLM sitemap files: ${error.message}`);
|
||||
console.log("\n⚠️ Skipping LLM sitemap generation due to errors");
|
||||
@@ -841,7 +856,7 @@ const fetchCategoryDataAndRender = () => {
|
||||
|
||||
const socket = io(socketUrl, {
|
||||
path: "/socket.io/",
|
||||
transports: [ "websocket"],
|
||||
transports: ["websocket"],
|
||||
reconnection: false,
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
BIN
public/assets/images/konfigurator.avif
Normal file
BIN
public/assets/images/konfigurator.avif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
BIN
public/assets/images/konfigurator.png
Normal file
BIN
public/assets/images/konfigurator.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 362 KiB |
@@ -7,6 +7,7 @@ const imagesToConvert = [
|
||||
{ src: 'seeds.jpg', dest: 'seeds.avif' },
|
||||
{ src: 'cutlings.jpg', dest: 'cutlings.avif' },
|
||||
{ src: 'gg.png', dest: 'gg.avif' },
|
||||
{ src: 'konfigurator.png', dest: 'konfigurator.avif' },
|
||||
{ src: 'maps.png', dest: 'maps.avif' }
|
||||
];
|
||||
|
||||
@@ -18,6 +19,7 @@ const run = async () => {
|
||||
const inputPath = path.join(imagesDir, image.src);
|
||||
const outputPath = path.join(imagesDir, image.dest);
|
||||
|
||||
console.log('d');
|
||||
if (!fs.existsSync(inputPath)) {
|
||||
console.warn(`⚠️ Input file not found: ${inputPath}`);
|
||||
continue;
|
||||
@@ -45,8 +47,8 @@ const run = async () => {
|
||||
hasError = true;
|
||||
}
|
||||
} else {
|
||||
// Silent skip if already up to date to keep logs clean, or use verbose flag
|
||||
// console.log(`Skipping ${image.src} (already up to date)`);
|
||||
// Silent skip if already up to date to keep logs clean, or use verbose flag
|
||||
// console.log(`Skipping ${image.src} (already up to date)`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,4 +57,5 @@ const run = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
console.log('dsfs');
|
||||
run();
|
||||
|
||||
30
src/App.js
30
src/App.js
@@ -50,6 +50,7 @@ const Datenschutz = lazy(() => import(/* webpackChunkName: "legal" */ "./pages/D
|
||||
const AGB = lazy(() => import(/* webpackChunkName: "legal" */ "./pages/AGB.js"));
|
||||
//const NotFound404 = lazy(() => import(/* webpackChunkName: "legal" */ "./pages/NotFound404.js")); <Route path="/404" element={<NotFound404 />} />
|
||||
const Sitemap = lazy(() => import(/* webpackChunkName: "sitemap" */ "./pages/Sitemap.js"));
|
||||
const CategoriesPage = lazy(() => import(/* webpackChunkName: "categories" */ "./pages/CategoriesPage.js"));
|
||||
const Impressum = lazy(() => import(/* webpackChunkName: "legal" */ "./pages/Impressum.js"));
|
||||
const Batteriegesetzhinweise = lazy(() => import(/* webpackChunkName: "legal" */ "./pages/Batteriegesetzhinweise.js"));
|
||||
const Widerrufsrecht = lazy(() => import(/* webpackChunkName: "legal" */ "./pages/Widerrufsrecht.js"));
|
||||
@@ -260,19 +261,19 @@ const AppContent = ({ currentTheme, dynamicTheme, onThemeChange }) => {
|
||||
{/* Category page - Render Content in parallel */}
|
||||
<Route
|
||||
path="/Kategorie/:categoryId"
|
||||
element={<Content/>}
|
||||
element={<Content />}
|
||||
/>
|
||||
{/* Single product page */}
|
||||
<Route
|
||||
path="/Artikel/:seoName"
|
||||
element={<ProductDetail/>}
|
||||
element={<ProductDetail />}
|
||||
/>
|
||||
|
||||
{/* Search page - Render Content in parallel */}
|
||||
<Route path="/search" element={<Content/>} />
|
||||
<Route path="/search" element={<Content />} />
|
||||
|
||||
{/* Profile page */}
|
||||
<Route path="/profile" element={<ProfilePage/>} />
|
||||
<Route path="/profile" element={<ProfilePage />} />
|
||||
|
||||
{/* Payment success page for Mollie redirects */}
|
||||
<Route path="/payment/success" element={<PaymentSuccess />} />
|
||||
@@ -280,22 +281,23 @@ const AppContent = ({ currentTheme, dynamicTheme, onThemeChange }) => {
|
||||
{/* Reset password page */}
|
||||
<Route
|
||||
path="/resetPassword"
|
||||
element={<ResetPassword/>}
|
||||
element={<ResetPassword />}
|
||||
/>
|
||||
|
||||
{/* Admin page */}
|
||||
<Route path="/admin" element={<AdminPage/>} />
|
||||
<Route path="/admin" element={<AdminPage />} />
|
||||
|
||||
{/* Admin Users page */}
|
||||
<Route path="/admin/users" element={<UsersPage/>} />
|
||||
<Route path="/admin/users" element={<UsersPage />} />
|
||||
|
||||
{/* Admin Server Logs page */}
|
||||
<Route path="/admin/logs" element={<ServerLogsPage/>} />
|
||||
<Route path="/admin/logs" element={<ServerLogsPage />} />
|
||||
|
||||
{/* Legal pages */}
|
||||
<Route path="/datenschutz" element={<Datenschutz />} />
|
||||
<Route path="/agb" element={<AGB />} />
|
||||
<Route path="/sitemap" element={<Sitemap />} />
|
||||
<Route path="/Kategorien" element={<CategoriesPage />} />
|
||||
<Route path="/impressum" element={<Impressum />} />
|
||||
<Route
|
||||
path="/batteriegesetzhinweise"
|
||||
@@ -304,7 +306,7 @@ const AppContent = ({ currentTheme, dynamicTheme, onThemeChange }) => {
|
||||
<Route path="/widerrufsrecht" element={<Widerrufsrecht />} />
|
||||
|
||||
{/* Grow Tent Configurator */}
|
||||
<Route path="/Konfigurator" element={<GrowTentKonfigurator/>} />
|
||||
<Route path="/Konfigurator" element={<GrowTentKonfigurator />} />
|
||||
|
||||
{/* Separate pages that are truly different */}
|
||||
<Route path="/presseverleih" element={<PresseverleihPage />} />
|
||||
@@ -457,11 +459,11 @@ const App = () => {
|
||||
<ProductContextProvider>
|
||||
<CategoryContextProvider>
|
||||
<CssBaseline />
|
||||
<AppContent
|
||||
currentTheme={currentTheme}
|
||||
dynamicTheme={dynamicTheme}
|
||||
onThemeChange={handleThemeChange}
|
||||
/>
|
||||
<AppContent
|
||||
currentTheme={currentTheme}
|
||||
dynamicTheme={dynamicTheme}
|
||||
onThemeChange={handleThemeChange}
|
||||
/>
|
||||
</CategoryContextProvider>
|
||||
</ProductContextProvider>
|
||||
</ThemeProvider>
|
||||
|
||||
118
src/PrerenderCategoriesPage.js
Normal file
118
src/PrerenderCategoriesPage.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import LegalPage from './pages/LegalPage.js';
|
||||
import CategoryBox from './components/CategoryBox.js';
|
||||
|
||||
const PrerenderCategoriesPage = ({ categoryData }) => {
|
||||
// Helper function to recursively collect all categories from the tree
|
||||
const collectAllCategories = (categoryNode, categories = [], level = 0) => {
|
||||
if (!categoryNode) return categories;
|
||||
|
||||
// Add current category (skip root category 209)
|
||||
if (categoryNode.id !== 209 && categoryNode.seoName) {
|
||||
categories.push({
|
||||
id: categoryNode.id,
|
||||
name: categoryNode.name,
|
||||
seoName: categoryNode.seoName,
|
||||
level: level
|
||||
});
|
||||
}
|
||||
|
||||
// Recursively add children
|
||||
if (categoryNode.children) {
|
||||
for (const child of categoryNode.children) {
|
||||
collectAllCategories(child, categories, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
// The categoryData passed prop is the root tree (id: 209)
|
||||
const rootTree = categoryData;
|
||||
|
||||
const renderLevel1Section = (l1Node) => {
|
||||
// Collect all descendants (excluding the L1 node itself, which collectAllCategories would include first)
|
||||
const descendants = collectAllCategories(l1Node).slice(1);
|
||||
|
||||
return (
|
||||
<Paper
|
||||
key={l1Node.id}
|
||||
elevation={1}
|
||||
sx={{
|
||||
p: 2,
|
||||
mb: 3,
|
||||
display: 'flex',
|
||||
flexDirection: { xs: 'column', md: 'row' },
|
||||
alignItems: { xs: 'flex-start', md: 'flex-start' },
|
||||
gap: 3
|
||||
}}
|
||||
>
|
||||
{/* Level 1 Header/Box */}
|
||||
<Box sx={{
|
||||
minWidth: '150px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: 1
|
||||
}}>
|
||||
<CategoryBox
|
||||
id={l1Node.id}
|
||||
name={l1Node.name}
|
||||
seoName={l1Node.seoName}
|
||||
sx={{
|
||||
boxShadow: 4,
|
||||
width: '150px',
|
||||
height: '150px'
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Descendants area */}
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
gap: 2
|
||||
}}>
|
||||
{descendants.map((cat) => (
|
||||
<CategoryBox
|
||||
key={cat.id}
|
||||
id={cat.id}
|
||||
name={cat.name}
|
||||
seoName={cat.seoName}
|
||||
sx={{
|
||||
width: '100px',
|
||||
height: '100px',
|
||||
minWidth: '100px',
|
||||
minHeight: '100px',
|
||||
boxShadow: 1,
|
||||
fontSize: '0.9rem'
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
const content = (
|
||||
<Box>
|
||||
<Box>
|
||||
{rootTree && rootTree.children && rootTree.children.map((child) => (
|
||||
renderLevel1Section(child)
|
||||
))}
|
||||
{(!rootTree || !rootTree.children || rootTree.children.length === 0) && (
|
||||
<Typography>Keine Kategorien gefunden.</Typography>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
return <LegalPage title="Kategorien" content={content} />;
|
||||
};
|
||||
|
||||
export default PrerenderCategoriesPage;
|
||||
@@ -352,6 +352,9 @@ class Footer extends Component {
|
||||
<Typography variant="body2" sx={{ fontSize: { xs: '11px', md: '14px' }, lineHeight: 1.5 }}>
|
||||
© {new Date().getFullYear()} <StyledDomainLink href="https://growheads.de" target="_blank" rel="noopener noreferrer">GrowHeads.de</StyledDomainLink>
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ fontSize: { xs: '9px', md: '9px' }, lineHeight: 1.5, mt: 1 }}>
|
||||
<StyledDomainLink href="https://telegraf.growheads.de" target="_blank" rel="noreferrer">Telegraf - sicherer Chat mit unseren Mitarbeitern</StyledDomainLink>
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
@@ -175,12 +175,12 @@ export class LoginComponent extends Component {
|
||||
const { location, navigate } = this.props;
|
||||
|
||||
if (!email || !password) {
|
||||
this.setState({ error: 'Bitte füllen Sie alle Felder aus' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.errors.fillAllFields') : 'Bitte füllen Sie alle Felder aus' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.validateEmail(email)) {
|
||||
this.setState({ error: 'Bitte geben Sie eine gültige E-Mail-Adresse ein' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.errors.invalidEmail') : 'Bitte geben Sie eine gültige E-Mail-Adresse ein' });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ export class LoginComponent extends Component {
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
error: response.message || 'Anmeldung fehlgeschlagen'
|
||||
error: response.message || (this.props.t ? this.props.t('auth.errors.loginFailed') : 'Anmeldung fehlgeschlagen')
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -248,22 +248,22 @@ export class LoginComponent extends Component {
|
||||
const { email, password, confirmPassword } = this.state;
|
||||
|
||||
if (!email || !password || !confirmPassword) {
|
||||
this.setState({ error: 'Bitte füllen Sie alle Felder aus' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.errors.fillAllFields') : 'Bitte füllen Sie alle Felder aus' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.validateEmail(email)) {
|
||||
this.setState({ error: 'Bitte geben Sie eine gültige E-Mail-Adresse ein' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.errors.invalidEmail') : 'Bitte geben Sie eine gültige E-Mail-Adresse ein' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
this.setState({ error: 'Passwörter stimmen nicht überein' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.errors.passwordsNotMatchShort') : 'Passwörter stimmen nicht überein' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.length < 8) {
|
||||
this.setState({ error: 'Das Passwort muss mindestens 8 Zeichen lang sein' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.passwordMinLength') : 'Das Passwort muss mindestens 8 Zeichen lang sein' });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -274,14 +274,14 @@ export class LoginComponent extends Component {
|
||||
if (response.success) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
success: 'Registrierung erfolgreich. Sie können sich jetzt anmelden.',
|
||||
success: this.props.t ? this.props.t('auth.success.registerComplete') : 'Registrierung erfolgreich. Sie können sich jetzt anmelden.',
|
||||
tabValue: 0 // Switch to login tab
|
||||
});
|
||||
} else {
|
||||
let errorMessage = 'Registrierung fehlgeschlagen';
|
||||
let errorMessage = this.props.t ? this.props.t('auth.errors.registerFailed') : 'Registrierung fehlgeschlagen';
|
||||
|
||||
if (response.cause === 'emailExists') {
|
||||
errorMessage = 'Ein Benutzer mit dieser E-Mail-Adresse existiert bereits. Bitte verwenden Sie eine andere E-Mail-Adresse oder melden Sie sich an.';
|
||||
errorMessage = this.props.t ? this.props.t('auth.errors.emailExists') : 'Ein Benutzer mit dieser E-Mail-Adresse existiert bereits. Bitte verwenden Sie eine andere E-Mail-Adresse oder melden Sie sich an.';
|
||||
} else if (response.message) {
|
||||
errorMessage = response.message;
|
||||
}
|
||||
@@ -322,12 +322,12 @@ export class LoginComponent extends Component {
|
||||
const { email } = this.state;
|
||||
|
||||
if (!email) {
|
||||
this.setState({ error: 'Bitte geben Sie Ihre E-Mail-Adresse ein' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.errors.enterEmail') : 'Bitte geben Sie Ihre E-Mail-Adresse ein' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.validateEmail(email)) {
|
||||
this.setState({ error: 'Bitte geben Sie eine gültige E-Mail-Adresse ein' });
|
||||
this.setState({ error: this.props.t ? this.props.t('auth.errors.invalidEmail') : 'Bitte geben Sie eine gültige E-Mail-Adresse ein' });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -342,12 +342,12 @@ export class LoginComponent extends Component {
|
||||
if (response.success) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
success: 'Ein Link zum Zurücksetzen des Passworts wurde an Ihre E-Mail-Adresse gesendet.'
|
||||
success: this.props.t ? this.props.t('auth.resetPassword.emailSent') : 'Ein Link zum Zurücksetzen des Passworts wurde an Ihre E-Mail-Adresse gesendet.'
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
error: response.message || 'Fehler beim Senden der E-Mail'
|
||||
error: response.message || (this.props.t ? this.props.t('auth.resetPassword.emailError') : 'Fehler beim Senden der E-Mail')
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -408,7 +408,7 @@ export class LoginComponent extends Component {
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
error: 'Google-Anmeldung fehlgeschlagen',
|
||||
error: this.props.t ? this.props.t('auth.errors.googleLoginFailed') : 'Google-Anmeldung fehlgeschlagen',
|
||||
showGoogleAuth: false // Reset Google auth state on failed login
|
||||
});
|
||||
}
|
||||
@@ -418,7 +418,7 @@ export class LoginComponent extends Component {
|
||||
handleGoogleLoginError = (error) => {
|
||||
console.error('Google Login Error:', error);
|
||||
this.setState({
|
||||
error: 'Google-Anmeldung fehlgeschlagen',
|
||||
error: this.props.t ? this.props.t('auth.errors.googleLoginFailed') : 'Google-Anmeldung fehlgeschlagen',
|
||||
showGoogleAuth: false, // Reset Google auth state on error
|
||||
loading: false
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
@@ -27,7 +28,7 @@ class SharedCarousel extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { i18n } = props;
|
||||
|
||||
|
||||
// Don't load categories in constructor - will be loaded in componentDidMount with correct language
|
||||
this.state = {
|
||||
categories: [],
|
||||
@@ -41,7 +42,7 @@ class SharedCarousel extends React.Component {
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n.language;
|
||||
|
||||
|
||||
// ALWAYS reload categories to ensure correct language
|
||||
console.log("SharedCarousel componentDidMount: ALWAYS RELOADING categories for language", currentLanguage);
|
||||
window.categoryService.get(209, currentLanguage).then((response) => {
|
||||
@@ -60,12 +61,12 @@ class SharedCarousel extends React.Component {
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
console.log("componentDidUpdate", prevProps.languageContext?.currentLanguage, this.props.languageContext?.currentLanguage);
|
||||
if(prevProps.languageContext?.currentLanguage !== this.props.languageContext?.currentLanguage) {
|
||||
this.setState({ categories: [] },() => {
|
||||
window.categoryService.get(209,this.props.languageContext?.currentLanguage || this.props.i18n.language).then((response) => {
|
||||
if (prevProps.languageContext?.currentLanguage !== this.props.languageContext?.currentLanguage) {
|
||||
this.setState({ categories: [] }, () => {
|
||||
window.categoryService.get(209, this.props.languageContext?.currentLanguage || this.props.i18n.language).then((response) => {
|
||||
console.log("response", response);
|
||||
if (response.children && response.children.length > 0) {
|
||||
this.originalCategories = response.children;
|
||||
this.originalCategories = response.children;
|
||||
this.categories = [...response.children, ...response.children];
|
||||
this.setState({ categories: this.categories });
|
||||
this.startAutoScroll();
|
||||
@@ -123,7 +124,7 @@ class SharedCarousel extends React.Component {
|
||||
showScrollbarFlash = () => {
|
||||
this.clearScrollbarTimer();
|
||||
this.setState({ showScrollbar: true });
|
||||
|
||||
|
||||
this.scrollbarTimer = setTimeout(() => {
|
||||
if (this._isMounted) {
|
||||
this.setState({ showScrollbar: false });
|
||||
@@ -133,7 +134,7 @@ class SharedCarousel extends React.Component {
|
||||
|
||||
handleAutoScroll = () => {
|
||||
if (!this.autoScrollActive || this.originalCategories.length === 0) return;
|
||||
|
||||
|
||||
this.translateX -= AUTO_SCROLL_SPEED;
|
||||
this.updateTrackTransform();
|
||||
|
||||
@@ -172,7 +173,7 @@ class SharedCarousel extends React.Component {
|
||||
|
||||
scrollBy = (direction) => {
|
||||
if (this.originalCategories.length === 0) return;
|
||||
|
||||
|
||||
// direction: 1 = left (scroll content right), -1 = right (scroll content left)
|
||||
const originalItemCount = this.originalCategories.length;
|
||||
const maxScroll = ITEM_WIDTH * originalItemCount;
|
||||
@@ -189,7 +190,7 @@ class SharedCarousel extends React.Component {
|
||||
}
|
||||
|
||||
this.updateTrackTransform();
|
||||
|
||||
|
||||
// Force scrollbar to update immediately after wrap-around
|
||||
if (this.state.showScrollbar) {
|
||||
this.forceUpdate();
|
||||
@@ -204,11 +205,11 @@ class SharedCarousel extends React.Component {
|
||||
const originalItemCount = this.originalCategories.length;
|
||||
const viewportWidth = 1080; // carousel container max-width
|
||||
const itemsInView = Math.floor(viewportWidth / ITEM_WIDTH);
|
||||
|
||||
|
||||
// Calculate which item is currently at the left edge (first visible)
|
||||
// Map translateX directly to item index using the same logic as scrollBy
|
||||
let currentItemIndex;
|
||||
|
||||
|
||||
if (this.translateX === 0) {
|
||||
// At the beginning - item 0 is visible
|
||||
currentItemIndex = 0;
|
||||
@@ -221,10 +222,10 @@ class SharedCarousel extends React.Component {
|
||||
// Normal negative scrolling - calculate which item is at left edge
|
||||
currentItemIndex = Math.floor(Math.abs(this.translateX) / ITEM_WIDTH);
|
||||
}
|
||||
|
||||
|
||||
// Ensure we stay within bounds
|
||||
currentItemIndex = Math.max(0, Math.min(currentItemIndex, originalItemCount - 1));
|
||||
|
||||
|
||||
// Calculate scrollbar position: 0% when item 0 is first visible, 100% when last item is first visible
|
||||
const lastPossibleFirstItem = Math.max(0, originalItemCount - itemsInView);
|
||||
const thumbPosition = lastPossibleFirstItem > 0 ? Math.min((currentItemIndex / lastPossibleFirstItem) * 100, 100) : 0;
|
||||
@@ -268,25 +269,41 @@ class SharedCarousel extends React.Component {
|
||||
const { t } = this.props;
|
||||
const { categories } = this.state;
|
||||
|
||||
if(!categories || categories.length === 0) {
|
||||
if (!categories || categories.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h1"
|
||||
<Box
|
||||
component={Link}
|
||||
to="/Kategorien"
|
||||
sx={{
|
||||
mb: 2,
|
||||
fontFamily: "SwashingtonCP",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
textDecoration: "none",
|
||||
color: "primary.main",
|
||||
textAlign: "center",
|
||||
textShadow: "3px 3px 10px rgba(0, 0, 0, 0.4)"
|
||||
mb: 2,
|
||||
transition: "all 0.3s ease",
|
||||
"&:hover": {
|
||||
transform: "translateX(5px)",
|
||||
color: "primary.dark"
|
||||
}
|
||||
}}
|
||||
>
|
||||
{t('navigation.categories')}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="span"
|
||||
sx={{
|
||||
fontFamily: "SwashingtonCP",
|
||||
textShadow: "3px 3px 10px rgba(0, 0, 0, 0.4)"
|
||||
}}
|
||||
>
|
||||
{t('navigation.categories')}
|
||||
</Typography>
|
||||
<ChevronRight sx={{ fontSize: "2.5rem", ml: 1 }} />
|
||||
</Box>
|
||||
|
||||
<div
|
||||
className="carousel-wrapper"
|
||||
@@ -394,7 +411,7 @@ class SharedCarousel extends React.Component {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
{/* Virtual Scrollbar */}
|
||||
{this.renderVirtualScrollbar()}
|
||||
</div>
|
||||
|
||||
@@ -32,9 +32,9 @@ class CategoryList extends Component {
|
||||
console.log(" i18n.language:", this.props.i18n?.language);
|
||||
console.log(" sessionStorage i18nextLng:", typeof sessionStorage !== 'undefined' ? sessionStorage.getItem('i18nextLng') : 'N/A');
|
||||
console.log(" localStorage i18nextLng:", typeof localStorage !== 'undefined' ? localStorage.getItem('i18nextLng') : 'N/A');
|
||||
|
||||
|
||||
const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n.language;
|
||||
|
||||
|
||||
// ALWAYS reload categories to ensure correct language
|
||||
console.log("CategoryList componentDidMount: ALWAYS RELOADING categories for language", currentLanguage);
|
||||
this.setState({ categories: [] }); // Clear any cached categories
|
||||
@@ -53,15 +53,15 @@ class CategoryList extends Component {
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
console.log("componentDidUpdate", prevProps.languageContext?.currentLanguage, this.props.languageContext?.currentLanguage);
|
||||
if(prevProps.languageContext?.currentLanguage !== this.props.languageContext?.currentLanguage) {
|
||||
if (prevProps.languageContext?.currentLanguage !== this.props.languageContext?.currentLanguage) {
|
||||
this.setState({
|
||||
categories: [],
|
||||
activeCategoryId: null
|
||||
},() => {
|
||||
window.categoryService.get(209,this.props.languageContext?.currentLanguage || this.props.i18n.language).then((response) => {
|
||||
}, () => {
|
||||
window.categoryService.get(209, this.props.languageContext?.currentLanguage || this.props.i18n.language).then((response) => {
|
||||
console.log("response", response);
|
||||
if (response.children && response.children.length > 0) {
|
||||
this.setState({
|
||||
this.setState({
|
||||
categories: response.children,
|
||||
activeCategoryId: this.setLevel1CategoryId(this.props.activeCategoryId)
|
||||
});
|
||||
@@ -69,14 +69,14 @@ class CategoryList extends Component {
|
||||
});
|
||||
});
|
||||
}
|
||||
if (prevProps.activeCategoryId !== this.props.activeCategoryId) {
|
||||
this.setLevel1CategoryId(this.props.activeCategoryId);
|
||||
}
|
||||
if (prevProps.activeCategoryId !== this.props.activeCategoryId) {
|
||||
this.setLevel1CategoryId(this.props.activeCategoryId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setLevel1CategoryId = (input) => {
|
||||
if(input) {
|
||||
if (input) {
|
||||
const language = this.props.languageContext?.currentLanguage || this.props.i18n.language;
|
||||
const categoryTreeCache = window.categoryService.getSync(209, language);
|
||||
|
||||
@@ -136,7 +136,7 @@ class CategoryList extends Component {
|
||||
this.setState({ activeCategoryId: null });
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
handleMobileMenuToggle = () => {
|
||||
this.setState(prevState => ({
|
||||
@@ -173,141 +173,141 @@ class CategoryList extends Component {
|
||||
py: 0.5, // Add vertical padding to prevent border clipping
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
component={Link}
|
||||
to="/"
|
||||
color="inherit"
|
||||
size="small"
|
||||
aria-label="Zur Startseite"
|
||||
onClick={isMobile ? this.handleMobileCategoryClick : undefined}
|
||||
sx={{
|
||||
fontSize: "0.75rem",
|
||||
textTransform: "none",
|
||||
whiteSpace: "nowrap",
|
||||
opacity: 0.9,
|
||||
mx: isMobile ? 0 : 0.5,
|
||||
my: 0.25,
|
||||
minWidth: isMobile ? "100%" : "auto",
|
||||
borderRadius: 1,
|
||||
justifyContent: isMobile ? "flex-start" : "center",
|
||||
transition: "all 0.2s ease",
|
||||
textShadow: "0 1px 2px rgba(0,0,0,0.3)",
|
||||
position: "relative",
|
||||
...(activeCategoryId === null && {
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
opacity: 1,
|
||||
}),
|
||||
"&:hover": {
|
||||
opacity: 1,
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
"& .bold-text": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
"& .thin-text": {
|
||||
color: "transparent !important",
|
||||
},
|
||||
<Button
|
||||
component={Link}
|
||||
to="/"
|
||||
color="inherit"
|
||||
size="small"
|
||||
aria-label="Zur Startseite"
|
||||
onClick={isMobile ? this.handleMobileCategoryClick : undefined}
|
||||
sx={{
|
||||
fontSize: "0.75rem",
|
||||
textTransform: "none",
|
||||
whiteSpace: "nowrap",
|
||||
opacity: 0.9,
|
||||
mx: isMobile ? 0 : 0.5,
|
||||
my: 0.25,
|
||||
minWidth: isMobile ? "100%" : "auto",
|
||||
borderRadius: 1,
|
||||
justifyContent: isMobile ? "flex-start" : "center",
|
||||
transition: "all 0.2s ease",
|
||||
textShadow: "0 1px 2px rgba(0,0,0,0.3)",
|
||||
position: "relative",
|
||||
...(activeCategoryId === null && {
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
opacity: 1,
|
||||
}),
|
||||
"&:hover": {
|
||||
opacity: 1,
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<HomeIcon sx={{
|
||||
fontSize: "1rem",
|
||||
mr: isMobile ? 1 : 0,
|
||||
color: activeCategoryId === null ? "#2e7d32" : "inherit"
|
||||
}} />
|
||||
{isMobile && (
|
||||
<Box sx={{ position: "relative", display: "inline-block" }}>
|
||||
{/* Bold text (always rendered to set width) */}
|
||||
<Box
|
||||
className="bold-text"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: activeCategoryId === null ? "#2e7d32" : "transparent",
|
||||
position: "relative",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
{/* Thin text (positioned on top) */}
|
||||
<Box
|
||||
className="thin-text"
|
||||
sx={{
|
||||
fontWeight: "400",
|
||||
color: activeCategoryId === null ? "transparent" : "inherit",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
"& .bold-text": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
"& .thin-text": {
|
||||
color: "transparent !important",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<HomeIcon sx={{
|
||||
fontSize: "1rem",
|
||||
mr: isMobile ? 1 : 0,
|
||||
color: activeCategoryId === null ? "#2e7d32" : "inherit"
|
||||
}} />
|
||||
{isMobile && (
|
||||
<Box sx={{ position: "relative", display: "inline-block" }}>
|
||||
{/* Bold text (always rendered to set width) */}
|
||||
<Box
|
||||
className="bold-text"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: activeCategoryId === null ? "#2e7d32" : "transparent",
|
||||
position: "relative",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
)}
|
||||
</Button>
|
||||
{/* Thin text (positioned on top) */}
|
||||
<Box
|
||||
className="thin-text"
|
||||
sx={{
|
||||
fontWeight: "400",
|
||||
color: activeCategoryId === null ? "transparent" : "inherit",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
component={Link}
|
||||
to="/Kategorie/neu"
|
||||
color="inherit"
|
||||
size="small"
|
||||
aria-label="Neuheiten"
|
||||
onClick={isMobile ? this.handleMobileCategoryClick : undefined}
|
||||
sx={{
|
||||
fontSize: "0.75rem",
|
||||
textTransform: "none",
|
||||
whiteSpace: "nowrap",
|
||||
opacity: 0.9,
|
||||
mx: isMobile ? 0 : 0.5,
|
||||
my: 0.25,
|
||||
minWidth: isMobile ? "100%" : "auto",
|
||||
borderRadius: 1,
|
||||
justifyContent: isMobile ? "flex-start" : "center",
|
||||
transition: "all 0.2s ease",
|
||||
textShadow: "0 1px 2px rgba(0,0,0,0.3)",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<FiberNewIcon sx={{
|
||||
fontSize: "1rem",
|
||||
mr: isMobile ? 1 : 0
|
||||
}} />
|
||||
{isMobile && (
|
||||
<Box sx={{ position: "relative", display: "inline-block" }}>
|
||||
{/* Bold text (always rendered to set width) */}
|
||||
<Box
|
||||
className="bold-text"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: "transparent",
|
||||
position: "relative",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.new') : 'Neuheiten'}
|
||||
</Box>
|
||||
{/* Thin text (positioned on top) */}
|
||||
<Box
|
||||
className="thin-text"
|
||||
sx={{
|
||||
fontWeight: "400",
|
||||
color: "inherit",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.new') : 'Neuheiten'}
|
||||
</Box>
|
||||
<Button
|
||||
component={Link}
|
||||
to="/Kategorie/neu"
|
||||
color="inherit"
|
||||
size="small"
|
||||
aria-label="Neuheiten"
|
||||
onClick={isMobile ? this.handleMobileCategoryClick : undefined}
|
||||
sx={{
|
||||
fontSize: "0.75rem",
|
||||
textTransform: "none",
|
||||
whiteSpace: "nowrap",
|
||||
opacity: 0.9,
|
||||
mx: isMobile ? 0 : 0.5,
|
||||
my: 0.25,
|
||||
minWidth: isMobile ? "100%" : "auto",
|
||||
borderRadius: 1,
|
||||
justifyContent: isMobile ? "flex-start" : "center",
|
||||
transition: "all 0.2s ease",
|
||||
textShadow: "0 1px 2px rgba(0,0,0,0.3)",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<FiberNewIcon sx={{
|
||||
fontSize: "1rem",
|
||||
mr: isMobile ? 1 : 0
|
||||
}} />
|
||||
{isMobile && (
|
||||
<Box sx={{ position: "relative", display: "inline-block" }}>
|
||||
{/* Bold text (always rendered to set width) */}
|
||||
<Box
|
||||
className="bold-text"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: "transparent",
|
||||
position: "relative",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.new') : 'Neuheiten'}
|
||||
</Box>
|
||||
)}
|
||||
</Button>
|
||||
{/* Thin text (positioned on top) */}
|
||||
<Box
|
||||
className="thin-text"
|
||||
sx={{
|
||||
fontWeight: "400",
|
||||
color: "inherit",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.new') : 'Neuheiten'}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
|
||||
{categories.length > 0 ? (
|
||||
@@ -385,100 +385,100 @@ class CategoryList extends Component {
|
||||
);
|
||||
})}
|
||||
</>
|
||||
) : ( !isMobile && (
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="inherit"
|
||||
sx={{
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
height: "33px", // Match small button height
|
||||
px: 1,
|
||||
fontSize: "0.75rem",
|
||||
opacity: 0.9,
|
||||
}}
|
||||
>
|
||||
|
||||
</Typography>
|
||||
)
|
||||
)}
|
||||
<Button
|
||||
component={Link}
|
||||
to="/Konfigurator"
|
||||
) : (!isMobile && (
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="inherit"
|
||||
size="small"
|
||||
aria-label="Zur Startseite"
|
||||
onClick={isMobile ? this.handleMobileCategoryClick : undefined}
|
||||
sx={{
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
height: "33px", // Match small button height
|
||||
px: 1,
|
||||
fontSize: "0.75rem",
|
||||
textTransform: "none",
|
||||
whiteSpace: "nowrap",
|
||||
opacity: 0.9,
|
||||
mx: isMobile ? 0 : 0.5,
|
||||
my: 0.25,
|
||||
minWidth: isMobile ? "100%" : "auto",
|
||||
borderRadius: 1,
|
||||
justifyContent: isMobile ? "flex-start" : "center",
|
||||
transition: "all 0.2s ease",
|
||||
textShadow: "0 1px 2px rgba(0,0,0,0.3)",
|
||||
position: "relative",
|
||||
...(activeCategoryId === null && {
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
opacity: 1,
|
||||
}),
|
||||
"&:hover": {
|
||||
opacity: 1,
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
"& .bold-text": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
"& .thin-text": {
|
||||
color: "transparent !important",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SettingsIcon sx={{
|
||||
fontSize: "1rem",
|
||||
mr: isMobile ? 1 : 0,
|
||||
color: activeCategoryId === null ? "#2e7d32" : "inherit"
|
||||
}} />
|
||||
{isMobile && (
|
||||
<Box sx={{ position: "relative", display: "inline-block" }}>
|
||||
{/* Bold text (always rendered to set width) */}
|
||||
<Box
|
||||
className="bold-text"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: activeCategoryId === null ? "#2e7d32" : "transparent",
|
||||
position: "relative",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
{/* Thin text (positioned on top) */}
|
||||
<Box
|
||||
className="thin-text"
|
||||
sx={{
|
||||
fontWeight: "400",
|
||||
color: activeCategoryId === null ? "transparent" : "inherit",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
|
||||
</Typography>
|
||||
)
|
||||
)}
|
||||
<Button
|
||||
component={Link}
|
||||
to="/Konfigurator"
|
||||
color="inherit"
|
||||
size="small"
|
||||
aria-label="Zur Startseite"
|
||||
onClick={isMobile ? this.handleMobileCategoryClick : undefined}
|
||||
sx={{
|
||||
fontSize: "0.75rem",
|
||||
textTransform: "none",
|
||||
whiteSpace: "nowrap",
|
||||
opacity: 0.9,
|
||||
mx: isMobile ? 0 : 0.5,
|
||||
my: 0.25,
|
||||
minWidth: isMobile ? "100%" : "auto",
|
||||
borderRadius: 1,
|
||||
justifyContent: isMobile ? "flex-start" : "center",
|
||||
transition: "all 0.2s ease",
|
||||
textShadow: "0 1px 2px rgba(0,0,0,0.3)",
|
||||
position: "relative",
|
||||
...(activeCategoryId === null && {
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
opacity: 1,
|
||||
}),
|
||||
"&:hover": {
|
||||
opacity: 1,
|
||||
bgcolor: "#fff",
|
||||
textShadow: "none",
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
"& .bold-text": {
|
||||
color: "#2e7d32 !important",
|
||||
},
|
||||
"& .thin-text": {
|
||||
color: "transparent !important",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SettingsIcon sx={{
|
||||
fontSize: "1rem",
|
||||
mr: isMobile ? 1 : 0,
|
||||
color: activeCategoryId === null ? "#2e7d32" : "inherit"
|
||||
}} />
|
||||
{isMobile && (
|
||||
<Box sx={{ position: "relative", display: "inline-block" }}>
|
||||
{/* Bold text (always rendered to set width) */}
|
||||
<Box
|
||||
className="bold-text"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: activeCategoryId === null ? "#2e7d32" : "transparent",
|
||||
position: "relative",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
)}
|
||||
</Button>
|
||||
{/* Thin text (positioned on top) */}
|
||||
<Box
|
||||
className="thin-text"
|
||||
sx={{
|
||||
fontWeight: "400",
|
||||
color: activeCategoryId === null ? "transparent" : "inherit",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
{this.props.t ? this.props.t('navigation.home') : 'Startseite'}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
</Box>
|
||||
);
|
||||
@@ -516,11 +516,11 @@ class CategoryList extends Component {
|
||||
>
|
||||
<Container maxWidth="lg" sx={{ px: 2 }}>
|
||||
{/* Toggle Button */}
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
py: 1,
|
||||
cursor: "pointer",
|
||||
"&:hover": {
|
||||
@@ -530,7 +530,7 @@ class CategoryList extends Component {
|
||||
onClick={this.handleMobileMenuToggle}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={this.props.t ?
|
||||
aria-label={this.props.t ?
|
||||
(mobileMenuOpen ? this.props.t('navigation.categoriesClose') : this.props.t('navigation.categoriesOpen')) :
|
||||
(mobileMenuOpen ? "Kategorien schließen" : "Kategorien öffnen")
|
||||
}
|
||||
@@ -541,11 +541,11 @@ class CategoryList extends Component {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Typography variant="subtitle2" color="inherit" sx={{
|
||||
<Typography variant="subtitle2" color="inherit" sx={{
|
||||
fontWeight: "bold",
|
||||
textShadow: "0 1px 2px rgba(0,0,0,0.3)"
|
||||
}}>
|
||||
{this.props.t ? this.props.t('navigation.categories') : 'Kategorien'}
|
||||
{this.props.t ? this.props.t('navigation.categories') : 'Kategorien'}
|
||||
</Typography>
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
{mobileMenuOpen ? <CloseIcon /> : <MenuIcon />}
|
||||
|
||||
@@ -31,6 +31,7 @@ const getStatusTranslation = (status, t) => {
|
||||
new: t ? t('orders.status.new') : "in Bearbeitung",
|
||||
pending: t ? t('orders.status.pending') : "Neu",
|
||||
processing: t ? t('orders.status.processing') : "in Bearbeitung",
|
||||
paid: t ? t('orders.status.paid') : "Bezahlt",
|
||||
cancelled: t ? t('orders.status.cancelled') : "Storniert",
|
||||
shipped: t ? t('orders.status.shipped') : "Verschickt",
|
||||
delivered: t ? t('orders.status.delivered') : "Geliefert",
|
||||
@@ -39,29 +40,23 @@ const getStatusTranslation = (status, t) => {
|
||||
};
|
||||
|
||||
const statusEmojis = {
|
||||
"in Bearbeitung": "⚙️",
|
||||
new: "⚙️",
|
||||
pending: "⏳",
|
||||
processing: "🔄",
|
||||
paid: "🏦",
|
||||
cancelled: "❌",
|
||||
Verschickt: "🚚",
|
||||
Geliefert: "✅",
|
||||
Storniert: "❌",
|
||||
Retoure: "↩️",
|
||||
"Teil Retoure": "↪️",
|
||||
"Teil geliefert": "⚡",
|
||||
shipped: "🚚",
|
||||
delivered: "✅",
|
||||
};
|
||||
|
||||
const statusColors = {
|
||||
"in Bearbeitung": "#ed6c02", // orange
|
||||
new: "#ed6c02", // orange
|
||||
pending: "#ff9800", // orange for pending
|
||||
processing: "#2196f3", // blue for processing
|
||||
paid: "#2e7d32", // green
|
||||
cancelled: "#d32f2f", // red for cancelled
|
||||
Verschickt: "#2e7d32", // green
|
||||
Geliefert: "#2e7d32", // green
|
||||
Storniert: "#d32f2f", // red
|
||||
Retoure: "#9c27b0", // purple
|
||||
"Teil Retoure": "#9c27b0", // purple
|
||||
"Teil geliefert": "#009688", // teal
|
||||
shipped: "#2e7d32", // green
|
||||
delivered: "#2e7d32", // green
|
||||
};
|
||||
|
||||
const currencyFormatter = new Intl.NumberFormat("de-DE", {
|
||||
@@ -229,11 +224,11 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "8px",
|
||||
color: getStatusColor(displayStatus),
|
||||
color: getStatusColor(order.status),
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: "1.2rem" }}>
|
||||
{getStatusEmoji(displayStatus)}
|
||||
{getStatusEmoji(order.status)}
|
||||
</span>
|
||||
<Typography
|
||||
variant="body2"
|
||||
@@ -243,6 +238,18 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
|
||||
{displayStatus}
|
||||
</Typography>
|
||||
</Box>
|
||||
{order.delivery_method === 'DHL' && order.trackingCode && (
|
||||
<Box sx={{ mt: 0.5 }}>
|
||||
<a
|
||||
href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${order.trackingCode}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{ fontSize: '0.85rem', color: '#d40511' }}
|
||||
>
|
||||
📦 {t ? t('orders.trackShipment') : 'Sendung verfolgen'}
|
||||
</a>
|
||||
</Box>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{order.items
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "الملف الشخصي",
|
||||
"email": "البريد الإلكتروني",
|
||||
"password": "كلمة المرور",
|
||||
"newPassword": "كلمة المرور الجديدة",
|
||||
"confirmPassword": "تأكيد كلمة المرور",
|
||||
"forgotPassword": "هل نسيت كلمة المرور؟",
|
||||
"loginWithGoogle": "تسجيل الدخول باستخدام جوجل",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "سياسة الخصوصية",
|
||||
"passwordMinLength": "يجب أن تكون كلمة المرور 8 أحرف على الأقل",
|
||||
"newPasswordMinLength": "يجب أن تكون كلمة المرور الجديدة 8 أحرف على الأقل",
|
||||
"backToHome": "العودة إلى الصفحة الرئيسية",
|
||||
"menu": {
|
||||
"profile": "الملف الشخصي",
|
||||
"myProfile": "ملفي الشخصي",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "الإعدادات",
|
||||
"adminDashboard": "لوحة تحكم المسؤول",
|
||||
"adminUsers": "مستخدمو المسؤول"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "إعادة تعيين كلمة المرور",
|
||||
"button": "إعادة تعيين كلمة المرور",
|
||||
"success": "تم إعادة تعيين كلمة المرور بنجاح! سيتم توجيهك لتسجيل الدخول قريبًا...",
|
||||
"invalidToken": "لم يتم العثور على رمز صالح. يرجى استخدام الرابط من بريدك الإلكتروني.",
|
||||
"error": "حدث خطأ أثناء إعادة تعيين كلمة المرور",
|
||||
"emailSent": "تم إرسال رابط لإعادة تعيين كلمة المرور إلى بريدك الإلكتروني.",
|
||||
"emailError": "حدث خطأ أثناء إرسال البريد الإلكتروني"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "يرجى ملء جميع الحقول",
|
||||
"invalidEmail": "يرجى إدخال بريد إلكتروني صالح",
|
||||
"passwordsNotMatch": "كلمات المرور غير متطابقة",
|
||||
"passwordsNotMatchShort": "كلمات المرور غير متطابقة",
|
||||
"enterEmail": "يرجى إدخال بريدك الإلكتروني",
|
||||
"loginFailed": "فشل تسجيل الدخول",
|
||||
"registerFailed": "فشل التسجيل",
|
||||
"googleLoginFailed": "فشل تسجيل الدخول عبر جوجل",
|
||||
"emailExists": "يوجد مستخدم بهذا البريد الإلكتروني بالفعل. يرجى استخدام بريد إلكتروني آخر أو تسجيل الدخول."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "تم التسجيل بنجاح. يمكنك الآن تسجيل الدخول."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,8 @@ export default {
|
||||
"new": "قيد التنفيذ",
|
||||
"pending": "جديد",
|
||||
"processing": "قيد التنفيذ",
|
||||
"cancelled": "ملغاة",
|
||||
"paid": "مدفوع",
|
||||
"cancelled": "ملغي",
|
||||
"shipped": "تم الشحن",
|
||||
"delivered": "تم التوصيل",
|
||||
"return": "إرجاع",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "إلغاء الطلب"
|
||||
},
|
||||
"noOrders": "لم تقم بوضع أي طلبات بعد.",
|
||||
"trackShipment": "تتبع الشحنة",
|
||||
"details": {
|
||||
"title": "تفاصيل الطلب: {{orderId}}",
|
||||
"deliveryAddress": "عنوان التوصيل",
|
||||
@@ -36,14 +38,13 @@ export default {
|
||||
"item": "العنصر",
|
||||
"quantity": "الكمية",
|
||||
"price": "السعر",
|
||||
"vat": "ضريبة القيمة المضافة",
|
||||
"total": "الإجمالي",
|
||||
"cancelOrder": "إلغاء الطلب"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "إلغاء الطلب",
|
||||
"message": "هل أنت متأكد أنك تريد إلغاء هذا الطلب؟",
|
||||
"confirm": "إلغاء الطلب",
|
||||
"confirm": "إلغاء",
|
||||
"cancelling": "جارٍ الإلغاء..."
|
||||
},
|
||||
"processing": "يتم إكمال الطلب..."
|
||||
|
||||
@@ -5,14 +5,16 @@ export default {
|
||||
"profile": "Профил",
|
||||
"email": "Имейл",
|
||||
"password": "Парола",
|
||||
"newPassword": "Нова парола",
|
||||
"confirmPassword": "Потвърдете паролата",
|
||||
"forgotPassword": "Забравена парола?",
|
||||
"loginWithGoogle": "Вход с Google",
|
||||
"or": "ИЛИ",
|
||||
"privacyAccept": "С натискане на \"Вход с Google\" приемам",
|
||||
"privacyAccept": "С натискането на \"Вход с Google\" приемам",
|
||||
"privacyPolicy": "Политиката за поверителност",
|
||||
"passwordMinLength": "Паролата трябва да е поне 8 символа",
|
||||
"newPasswordMinLength": "Новата парола трябва да е поне 8 символа",
|
||||
"backToHome": "Обратно към началната страница",
|
||||
"menu": {
|
||||
"profile": "Профил",
|
||||
"myProfile": "Моят профил",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Настройки",
|
||||
"adminDashboard": "Админ табло",
|
||||
"adminUsers": "Админ потребители"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Нулиране на парола",
|
||||
"button": "Нулиране на парола",
|
||||
"success": "Вашата парола беше успешно нулирана! Скоро ще бъдете пренасочени към вход...",
|
||||
"invalidToken": "Няма валиден токен. Моля, използвайте линка от имейла си.",
|
||||
"error": "Грешка при нулиране на паролата",
|
||||
"emailSent": "Линк за нулиране на паролата беше изпратен на вашия имейл.",
|
||||
"emailError": "Грешка при изпращане на имейла"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Моля, попълнете всички полета",
|
||||
"invalidEmail": "Моля, въведете валиден имейл адрес",
|
||||
"passwordsNotMatch": "Паролите не съвпадат",
|
||||
"passwordsNotMatchShort": "Паролите не съвпадат",
|
||||
"enterEmail": "Моля, въведете вашия имейл адрес",
|
||||
"loginFailed": "Входът не бе успешен",
|
||||
"registerFailed": "Регистрацията не бе успешна",
|
||||
"googleLoginFailed": "Вход с Google не бе успешен",
|
||||
"emailExists": "Потребител с този имейл вече съществува. Моля, използвайте друг имейл или влезте в системата."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Регистрацията беше успешна. Сега можете да влезете."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "В процес",
|
||||
"pending": "Нова",
|
||||
"processing": "В процес",
|
||||
"cancelled": "Отменена",
|
||||
"shipped": "Изпратена",
|
||||
"delivered": "Доставена",
|
||||
"new": "в процес",
|
||||
"pending": "Ново",
|
||||
"processing": "в процес",
|
||||
"paid": "Платено",
|
||||
"cancelled": "Отменено",
|
||||
"shipped": "Изпратено",
|
||||
"delivered": "Доставено",
|
||||
"return": "Връщане",
|
||||
"partialReturn": "Частично връщане",
|
||||
"partialDelivered": "Частично доставена"
|
||||
"partialDelivered": "Частично доставено"
|
||||
},
|
||||
"table": {
|
||||
"orderNumber": "Номер на поръчка",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Отмени поръчката"
|
||||
},
|
||||
"noOrders": "Все още не сте направили поръчки.",
|
||||
"trackShipment": "Проследи пратката",
|
||||
"details": {
|
||||
"title": "Подробности за поръчка: {{orderId}}",
|
||||
"deliveryAddress": "Адрес за доставка",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Артикул",
|
||||
"quantity": "Количество",
|
||||
"price": "Цена",
|
||||
"vat": "ДДС",
|
||||
"total": "Общо",
|
||||
"cancelOrder": "Отмени поръчката"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Отмяна на поръчка",
|
||||
"message": "Сигурни ли сте, че искате да отмените тази поръчка?",
|
||||
"confirm": "Отмени поръчката",
|
||||
"cancelling": "Отмяна..."
|
||||
"title": "Отмени поръчката",
|
||||
"message": "Сигурни ли сте, че искате да отмените тази поръчка?",
|
||||
"confirm": "Отмени",
|
||||
"cancelling": "Отмяна..."
|
||||
},
|
||||
"processing": "Поръчката се обработва...",
|
||||
"processing": "Поръчката се обработва..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Heslo",
|
||||
"newPassword": "Nové heslo",
|
||||
"confirmPassword": "Potvrdit heslo",
|
||||
"forgotPassword": "Zapomněli jste heslo?",
|
||||
"loginWithGoogle": "Přihlásit se přes Google",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Zásadami ochrany osobních údajů",
|
||||
"passwordMinLength": "Heslo musí mít alespoň 8 znaků",
|
||||
"newPasswordMinLength": "Nové heslo musí mít alespoň 8 znaků",
|
||||
"backToHome": "Zpět na domovskou stránku",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Můj profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Nastavení",
|
||||
"adminDashboard": "Admin Dashboard",
|
||||
"adminUsers": "Admin Users"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Obnovení hesla",
|
||||
"button": "Obnovit heslo",
|
||||
"success": "Vaše heslo bylo úspěšně obnoveno! Brzy budete přesměrováni na přihlášení...",
|
||||
"invalidToken": "Nebyl nalezen platný token. Použijte prosím odkaz z vašeho e-mailu.",
|
||||
"error": "Chyba při obnově hesla",
|
||||
"emailSent": "Odkaz pro obnovení hesla byl odeslán na vaši e-mailovou adresu.",
|
||||
"emailError": "Chyba při odesílání e-mailu"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Vyplňte prosím všechna pole",
|
||||
"invalidEmail": "Zadejte platnou e-mailovou adresu",
|
||||
"passwordsNotMatch": "Hesla se neshodují",
|
||||
"passwordsNotMatchShort": "Hesla se neshodují",
|
||||
"enterEmail": "Zadejte prosím svou e-mailovou adresu",
|
||||
"loginFailed": "Přihlášení selhalo",
|
||||
"registerFailed": "Registrace selhala",
|
||||
"googleLoginFailed": "Přihlášení přes Google selhalo",
|
||||
"emailExists": "Uživatel s touto e-mailovou adresou již existuje. Použijte prosím jinou e-mailovou adresu nebo se přihlaste."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registrace byla úspěšná. Nyní se můžete přihlásit."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,50 +1,51 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "Probíhá",
|
||||
"pending": "Nová",
|
||||
"processing": "Probíhá",
|
||||
"cancelled": "Zrušeno",
|
||||
"shipped": "Odesláno",
|
||||
"delivered": "Doručeno",
|
||||
"return": "Vrácení",
|
||||
"partialReturn": "Částečné vrácení",
|
||||
"partialDelivered": "Částečně doručeno"
|
||||
"new": "probíhá",
|
||||
"pending": "Nové",
|
||||
"processing": "probíhá",
|
||||
"paid": "Zaplaceno",
|
||||
"cancelled": "Zrušeno",
|
||||
"shipped": "Odesláno",
|
||||
"delivered": "Doručeno",
|
||||
"return": "Vrácení",
|
||||
"partialReturn": "Částečné vrácení",
|
||||
"partialDelivered": "Částečně doručeno"
|
||||
},
|
||||
"table": {
|
||||
"orderNumber": "Číslo objednávky",
|
||||
"date": "Datum",
|
||||
"status": "Stav",
|
||||
"items": "Položky",
|
||||
"total": "Celkem",
|
||||
"actions": "Akce",
|
||||
"viewDetails": "Zobrazit detaily"
|
||||
"orderNumber": "Číslo objednávky",
|
||||
"date": "Datum",
|
||||
"status": "Stav",
|
||||
"items": "Položky",
|
||||
"total": "Celkem",
|
||||
"actions": "Akce",
|
||||
"viewDetails": "Zobrazit detaily"
|
||||
},
|
||||
"tooltips": {
|
||||
"viewDetails": "Zobrazit detaily",
|
||||
"cancelOrder": "Zrušit objednávku"
|
||||
"viewDetails": "Zobrazit detaily",
|
||||
"cancelOrder": "Zrušit objednávku"
|
||||
},
|
||||
"noOrders": "Ještě jste neprovedli žádné objednávky.",
|
||||
"noOrders": "Ještě jste neprovedli žádné objednávky.",
|
||||
"trackShipment": "Sledovat zásilku",
|
||||
"details": {
|
||||
"title": "Detaily objednávky: {{orderId}}",
|
||||
"deliveryAddress": "Dodací adresa",
|
||||
"invoiceAddress": "Fakturační adresa",
|
||||
"orderDetails": "Detaily objednávky",
|
||||
"deliveryMethod": "Způsob doručení:",
|
||||
"paymentMethod": "Způsob platby:",
|
||||
"notSpecified": "Nespecifikováno",
|
||||
"orderedItems": "Objednané položky",
|
||||
"item": "Položka",
|
||||
"quantity": "Množství",
|
||||
"price": "Cena",
|
||||
"vat": "DPH",
|
||||
"total": "Celkem",
|
||||
"cancelOrder": "Zrušit objednávku"
|
||||
"title": "Detaily objednávky: {{orderId}}",
|
||||
"deliveryAddress": "Dodací adresa",
|
||||
"invoiceAddress": "Fakturační adresa",
|
||||
"orderDetails": "Detaily objednávky",
|
||||
"deliveryMethod": "Způsob doručení:",
|
||||
"paymentMethod": "Způsob platby:",
|
||||
"notSpecified": "Nespecifikováno",
|
||||
"orderedItems": "Objednané položky",
|
||||
"item": "Položka",
|
||||
"quantity": "Množství",
|
||||
"price": "Cena",
|
||||
"total": "Celkem",
|
||||
"cancelOrder": "Zrušit objednávku"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Zrušit objednávku",
|
||||
"message": "Opravdu chcete tuto objednávku zrušit?",
|
||||
"confirm": "Zrušit objednávku",
|
||||
"confirm": "Zrušit",
|
||||
"cancelling": "Rušení..."
|
||||
},
|
||||
"processing": "Objednávka se dokončuje...",
|
||||
"processing": "Objednávka se dokončuje..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "E-Mail",
|
||||
"password": "Passwort",
|
||||
"newPassword": "Neues Passwort",
|
||||
"confirmPassword": "Passwort bestätigen",
|
||||
"forgotPassword": "Passwort vergessen?",
|
||||
"loginWithGoogle": "Mit Google anmelden",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Datenschutzbestimmungen",
|
||||
"passwordMinLength": "Das Passwort muss mindestens 8 Zeichen lang sein",
|
||||
"newPasswordMinLength": "Das neue Passwort muss mindestens 8 Zeichen lang sein",
|
||||
"backToHome": "Zurück zur Startseite",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Mein Profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Einstellungen",
|
||||
"adminDashboard": "Admin Dashboard",
|
||||
"adminUsers": "Admin Users"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Passwort zurücksetzen",
|
||||
"button": "Passwort zurücksetzen",
|
||||
"success": "Ihr Passwort wurde erfolgreich zurückgesetzt! Sie werden in Kürze zur Anmeldung weitergeleitet...",
|
||||
"invalidToken": "Kein gültiger Token gefunden. Bitte verwenden Sie den Link aus Ihrer E-Mail.",
|
||||
"error": "Fehler beim Zurücksetzen des Passworts",
|
||||
"emailSent": "Ein Link zum Zurücksetzen des Passworts wurde an Ihre E-Mail-Adresse gesendet.",
|
||||
"emailError": "Fehler beim Senden der E-Mail"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Bitte füllen Sie alle Felder aus",
|
||||
"invalidEmail": "Bitte geben Sie eine gültige E-Mail-Adresse ein",
|
||||
"passwordsNotMatch": "Die Passwörter stimmen nicht überein",
|
||||
"passwordsNotMatchShort": "Passwörter stimmen nicht überein",
|
||||
"enterEmail": "Bitte geben Sie Ihre E-Mail-Adresse ein",
|
||||
"loginFailed": "Anmeldung fehlgeschlagen",
|
||||
"registerFailed": "Registrierung fehlgeschlagen",
|
||||
"googleLoginFailed": "Google-Anmeldung fehlgeschlagen",
|
||||
"emailExists": "Ein Benutzer mit dieser E-Mail-Adresse existiert bereits. Bitte verwenden Sie eine andere E-Mail-Adresse oder melden Sie sich an."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registrierung erfolgreich. Sie können sich jetzt anmelden."
|
||||
}
|
||||
};
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
"new": "in Bearbeitung",
|
||||
"pending": "Neu",
|
||||
"processing": "in Bearbeitung",
|
||||
"paid": "Bezahlt",
|
||||
"cancelled": "Storniert",
|
||||
"shipped": "Verschickt",
|
||||
"delivered": "Geliefert",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Bestellung stornieren"
|
||||
},
|
||||
"noOrders": "Sie haben noch keine Bestellungen aufgegeben.",
|
||||
"trackShipment": "Sendung verfolgen",
|
||||
"details": {
|
||||
"title": "Bestelldetails: {{orderId}}",
|
||||
"deliveryAddress": "Lieferadresse",
|
||||
|
||||
@@ -5,14 +5,16 @@ export default {
|
||||
"profile": "Προφίλ",
|
||||
"email": "Email",
|
||||
"password": "Κωδικός",
|
||||
"newPassword": "Νέος κωδικός",
|
||||
"confirmPassword": "Επιβεβαίωση κωδικού",
|
||||
"forgotPassword": "Ξεχάσατε τον κωδικό;",
|
||||
"loginWithGoogle": "Σύνδεση με Google",
|
||||
"or": "Ή",
|
||||
"privacyAccept": "Κάνοντας κλικ στο \"Σύνδεση με Google\" αποδέχομαι την",
|
||||
"privacyPolicy": "Πολιτική Απορρήτου",
|
||||
"privacyPolicy": "Πολιτική απορρήτου",
|
||||
"passwordMinLength": "Ο κωδικός πρέπει να έχει τουλάχιστον 8 χαρακτήρες",
|
||||
"newPasswordMinLength": "Ο νέος κωδικός πρέπει να έχει τουλάχιστον 8 χαρακτήρες",
|
||||
"backToHome": "Επιστροφή στην αρχική σελίδα",
|
||||
"menu": {
|
||||
"profile": "Προφίλ",
|
||||
"myProfile": "Το προφίλ μου",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Ρυθμίσεις",
|
||||
"adminDashboard": "Πίνακας διαχείρισης",
|
||||
"adminUsers": "Διαχειριστές"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Επαναφορά κωδικού",
|
||||
"button": "Επαναφορά κωδικού",
|
||||
"success": "Ο κωδικός σας επαναφέρθηκε με επιτυχία! Θα ανακατευθυνθείτε στη σύνδεση σύντομα...",
|
||||
"invalidToken": "Δεν βρέθηκε έγκυρο διακριτικό. Παρακαλώ χρησιμοποιήστε τον σύνδεσμο από το email σας.",
|
||||
"error": "Σφάλμα κατά την επαναφορά του κωδικού",
|
||||
"emailSent": "Ένας σύνδεσμος για επαναφορά του κωδικού σας έχει σταλεί στη διεύθυνση email σας.",
|
||||
"emailError": "Σφάλμα κατά την αποστολή του email"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Παρακαλώ συμπληρώστε όλα τα πεδία",
|
||||
"invalidEmail": "Παρακαλώ εισάγετε μια έγκυρη διεύθυνση email",
|
||||
"passwordsNotMatch": "Οι κωδικοί δεν ταιριάζουν",
|
||||
"passwordsNotMatchShort": "Οι κωδικοί δεν ταιριάζουν",
|
||||
"enterEmail": "Παρακαλώ εισάγετε τη διεύθυνση email σας",
|
||||
"loginFailed": "Η σύνδεση απέτυχε",
|
||||
"registerFailed": "Η εγγραφή απέτυχε",
|
||||
"googleLoginFailed": "Η σύνδεση με Google απέτυχε",
|
||||
"emailExists": "Υπάρχει ήδη χρήστης με αυτή τη διεύθυνση email. Παρακαλώ χρησιμοποιήστε άλλη διεύθυνση ή συνδεθείτε."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Η εγγραφή ολοκληρώθηκε με επιτυχία. Μπορείτε τώρα να συνδεθείτε."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "Σε εξέλιξη",
|
||||
"new": "σε εξέλιξη",
|
||||
"pending": "Νέο",
|
||||
"processing": "Σε εξέλιξη",
|
||||
"processing": "σε εξέλιξη",
|
||||
"paid": "Πληρωμένο",
|
||||
"cancelled": "Ακυρώθηκε",
|
||||
"shipped": "Απεστάλη",
|
||||
"shipped": "Απεσταλμένο",
|
||||
"delivered": "Παραδόθηκε",
|
||||
"return": "Επιστροφή",
|
||||
"partialReturn": "Μερική επιστροφή",
|
||||
@@ -24,10 +25,11 @@ export default {
|
||||
"cancelOrder": "Ακύρωση παραγγελίας"
|
||||
},
|
||||
"noOrders": "Δεν έχετε κάνει ακόμα καμία παραγγελία.",
|
||||
"trackShipment": "Παρακολούθηση αποστολής",
|
||||
"details": {
|
||||
"title": "Λεπτομέρειες παραγγελίας: {{orderId}}",
|
||||
"deliveryAddress": "Διεύθυνση παράδοσης",
|
||||
"invoiceAddress": "Διεύθυνση τιμολόγησης",
|
||||
"invoiceAddress": "Διεύθυνση τιμολογίου",
|
||||
"orderDetails": "Λεπτομέρειες παραγγελίας",
|
||||
"deliveryMethod": "Τρόπος παράδοσης:",
|
||||
"paymentMethod": "Τρόπος πληρωμής:",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Είδος",
|
||||
"quantity": "Ποσότητα",
|
||||
"price": "Τιμή",
|
||||
"vat": "ΦΠΑ",
|
||||
"total": "Σύνολο",
|
||||
"cancelOrder": "Ακύρωση παραγγελίας"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Ακύρωση παραγγελίας",
|
||||
"message": "Είστε σίγουροι ότι θέλετε να ακυρώσετε αυτήν την παραγγελία;",
|
||||
"confirm": "Ακύρωση παραγγελίας",
|
||||
"cancelling": "Ακύρωση..."
|
||||
"message": "Είστε σίγουροι ότι θέλετε να ακυρώσετε αυτή την παραγγελία;",
|
||||
"confirm": "Ακύρωση",
|
||||
"cancelling": "Ακύρωση σε εξέλιξη..."
|
||||
},
|
||||
"processing": "Η παραγγελία ολοκληρώνεται..."
|
||||
};
|
||||
|
||||
@@ -5,14 +5,16 @@ export default {
|
||||
"profile": "Profile", // Profil
|
||||
"email": "Email", // E-Mail
|
||||
"password": "Password", // Passwort
|
||||
"newPassword": "New password", // Neues Passwort
|
||||
"confirmPassword": "Confirm password", // Passwort bestätigen
|
||||
"forgotPassword": "Forgot password?", // Passwort vergessen?
|
||||
"loginWithGoogle": "Sign in with Google", // Mit Google anmelden
|
||||
"or": "OR", // ODER
|
||||
"privacyAccept": "By clicking \"Sign in with Google\" I accept the", // Mit dem Click auf "Mit Google anmelden" akzeptiere ich die
|
||||
"privacyPolicy": "Privacy Policy", // Datenschutzbestimmungen
|
||||
"privacyAccept": "By clicking on \"Sign in with Google\" I accept the", // Mit dem Click auf "Mit Google anmelden" akzeptiere ich die
|
||||
"privacyPolicy": "Privacy policy", // Datenschutzbestimmungen
|
||||
"passwordMinLength": "The password must be at least 8 characters long", // Das Passwort muss mindestens 8 Zeichen lang sein
|
||||
"newPasswordMinLength": "The new password must be at least 8 characters long", // Das neue Passwort muss mindestens 8 Zeichen lang sein
|
||||
"backToHome": "Back to homepage", // Zurück zur Startseite
|
||||
"menu": {
|
||||
"profile": "Profile", // Profil
|
||||
"myProfile": "My profile", // Mein Profil
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Settings", // Einstellungen
|
||||
"adminDashboard": "Admin Dashboard", // Admin Dashboard
|
||||
"adminUsers": "Admin Users" // Admin Users
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Reset password", // Passwort zurücksetzen
|
||||
"button": "Reset password", // Passwort zurücksetzen
|
||||
"success": "Your password has been reset successfully! You will be redirected to login shortly...", // Ihr Passwort wurde erfolgreich zurückgesetzt! Sie werden in Kürze zur Anmeldung weitergeleitet...
|
||||
"invalidToken": "No valid token found. Please use the link from your email.", // Kein gültiger Token gefunden. Bitte verwenden Sie den Link aus Ihrer E-Mail.
|
||||
"error": "Error resetting password", // Fehler beim Zurücksetzen des Passworts
|
||||
"emailSent": "A link to reset your password has been sent to your email address.", // Ein Link zum Zurücksetzen des Passworts wurde an Ihre E-Mail-Adresse gesendet.
|
||||
"emailError": "Error sending email" // Fehler beim Senden der E-Mail
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Please fill in all fields", // Bitte füllen Sie alle Felder aus
|
||||
"invalidEmail": "Please enter a valid email address", // Bitte geben Sie eine gültige E-Mail-Adresse ein
|
||||
"passwordsNotMatch": "The passwords do not match", // Die Passwörter stimmen nicht überein
|
||||
"passwordsNotMatchShort": "Passwords do not match", // Passwörter stimmen nicht überein
|
||||
"enterEmail": "Please enter your email address", // Bitte geben Sie Ihre E-Mail-Adresse ein
|
||||
"loginFailed": "Login failed", // Anmeldung fehlgeschlagen
|
||||
"registerFailed": "Registration failed", // Registrierung fehlgeschlagen
|
||||
"googleLoginFailed": "Google login failed", // Google-Anmeldung fehlgeschlagen
|
||||
"emailExists": "A user with this email address already exists. Please use another email address or log in." // Ein Benutzer mit dieser E-Mail-Adresse existiert bereits. Bitte verwenden Sie eine andere E-Mail-Adresse oder melden Sie sich an.
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registration successful. You can now log in." // Registrierung erfolgreich. Sie können sich jetzt anmelden.
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "In progress", // in Bearbeitung
|
||||
"new": "in progress", // in Bearbeitung
|
||||
"pending": "New", // Neu
|
||||
"processing": "In progress", // in Bearbeitung
|
||||
"processing": "in progress", // in Bearbeitung
|
||||
"paid": "Paid", // Bezahlt
|
||||
"cancelled": "Cancelled", // Storniert
|
||||
"shipped": "Shipped", // Verschickt
|
||||
"delivered": "Delivered", // Geliefert
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Cancel order" // Bestellung stornieren
|
||||
},
|
||||
"noOrders": "You have not placed any orders yet.", // Sie haben noch keine Bestellungen aufgegeben.
|
||||
"trackShipment": "Track shipment", // Sendung verfolgen
|
||||
"details": {
|
||||
"title": "Order details: {{orderId}}", // Bestelldetails: {{orderId}}
|
||||
"deliveryAddress": "Delivery address", // Lieferadresse
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Item", // Artikel
|
||||
"quantity": "Quantity", // Menge
|
||||
"price": "Price", // Preis
|
||||
"vat": "VAT", // MwSt.
|
||||
"total": "Total", // Gesamt
|
||||
"cancelOrder": "Cancel order" // Bestellung stornieren
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Cancel Order",
|
||||
"message": "Are you sure you want to cancel this order?",
|
||||
"confirm": "Cancel Order",
|
||||
"cancelling": "Cancelling..."
|
||||
"title": "Cancel order", // Bestellung stornieren
|
||||
"message": "Are you sure you want to cancel this order?", // Sind Sie sicher, dass Sie diese Bestellung stornieren möchten?
|
||||
"confirm": "Cancel", // Stornieren
|
||||
"cancelling": "Cancelling..." // Wird storniert...
|
||||
},
|
||||
"processing": "Order is being completed...", // Bestellung wird abgeschlossen...
|
||||
"processing": "Order is being completed..." // Bestellung wird abgeschlossen...
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Perfil",
|
||||
"email": "Correo electrónico",
|
||||
"password": "Contraseña",
|
||||
"newPassword": "Nueva contraseña",
|
||||
"confirmPassword": "Confirmar contraseña",
|
||||
"forgotPassword": "¿Olvidaste tu contraseña?",
|
||||
"loginWithGoogle": "Iniciar sesión con Google",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Política de privacidad",
|
||||
"passwordMinLength": "La contraseña debe tener al menos 8 caracteres",
|
||||
"newPasswordMinLength": "La nueva contraseña debe tener al menos 8 caracteres",
|
||||
"backToHome": "Volver a la página principal",
|
||||
"menu": {
|
||||
"profile": "Perfil",
|
||||
"myProfile": "Mi perfil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Configuración",
|
||||
"adminDashboard": "Panel de administración",
|
||||
"adminUsers": "Usuarios administradores"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Restablecer contraseña",
|
||||
"button": "Restablecer contraseña",
|
||||
"success": "¡Tu contraseña ha sido restablecida con éxito! Serás redirigido para iniciar sesión en breve...",
|
||||
"invalidToken": "No se encontró un token válido. Por favor, usa el enlace de tu correo electrónico.",
|
||||
"error": "Error al restablecer la contraseña",
|
||||
"emailSent": "Se ha enviado un enlace para restablecer tu contraseña a tu dirección de correo electrónico.",
|
||||
"emailError": "Error al enviar el correo electrónico"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Por favor, completa todos los campos",
|
||||
"invalidEmail": "Por favor, introduce una dirección de correo electrónico válida",
|
||||
"passwordsNotMatch": "Las contraseñas no coinciden",
|
||||
"passwordsNotMatchShort": "Las contraseñas no coinciden",
|
||||
"enterEmail": "Por favor, introduce tu dirección de correo electrónico",
|
||||
"loginFailed": "Error al iniciar sesión",
|
||||
"registerFailed": "Error al registrarse",
|
||||
"googleLoginFailed": "Error al iniciar sesión con Google",
|
||||
"emailExists": "Ya existe un usuario con esta dirección de correo electrónico. Por favor, usa otra dirección de correo electrónico o inicia sesión."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registro exitoso. Ahora puedes iniciar sesión."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "En progreso",
|
||||
"new": "en progreso",
|
||||
"pending": "Nuevo",
|
||||
"processing": "En progreso",
|
||||
"processing": "en progreso",
|
||||
"paid": "Pagado",
|
||||
"cancelled": "Cancelado",
|
||||
"shipped": "Enviado",
|
||||
"delivered": "Entregado",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Cancelar pedido"
|
||||
},
|
||||
"noOrders": "Aún no has realizado ningún pedido.",
|
||||
"trackShipment": "Rastrear envío",
|
||||
"details": {
|
||||
"title": "Detalles del pedido: {{orderId}}",
|
||||
"deliveryAddress": "Dirección de entrega",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Artículo",
|
||||
"quantity": "Cantidad",
|
||||
"price": "Precio",
|
||||
"vat": "IVA",
|
||||
"total": "Total",
|
||||
"cancelOrder": "Cancelar pedido"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Cancelar pedido",
|
||||
"message": "¿Estás seguro de que deseas cancelar este pedido?",
|
||||
"confirm": "Cancelar pedido",
|
||||
"message": "¿Está seguro de que desea cancelar este pedido?",
|
||||
"confirm": "Cancelar",
|
||||
"cancelling": "Cancelando..."
|
||||
},
|
||||
"processing": "El pedido se está completando...",
|
||||
"processing": "El pedido se está completando..."
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
export default {
|
||||
"login": "Connexion",
|
||||
"register": "S'inscrire",
|
||||
"register": "Inscription",
|
||||
"logout": "Déconnexion",
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Mot de passe",
|
||||
"newPassword": "Nouveau mot de passe",
|
||||
"confirmPassword": "Confirmer le mot de passe",
|
||||
"forgotPassword": "Mot de passe oublié ?",
|
||||
"loginWithGoogle": "Se connecter avec Google",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Politique de confidentialité",
|
||||
"passwordMinLength": "Le mot de passe doit contenir au moins 8 caractères",
|
||||
"newPasswordMinLength": "Le nouveau mot de passe doit contenir au moins 8 caractères",
|
||||
"backToHome": "Retour à la page d'accueil",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Mon profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Paramètres",
|
||||
"adminDashboard": "Tableau de bord Admin",
|
||||
"adminUsers": "Utilisateurs Admin"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Réinitialiser le mot de passe",
|
||||
"button": "Réinitialiser le mot de passe",
|
||||
"success": "Votre mot de passe a été réinitialisé avec succès ! Vous serez redirigé vers la connexion sous peu...",
|
||||
"invalidToken": "Aucun jeton valide trouvé. Veuillez utiliser le lien de votre email.",
|
||||
"error": "Erreur lors de la réinitialisation du mot de passe",
|
||||
"emailSent": "Un lien pour réinitialiser votre mot de passe a été envoyé à votre adresse email.",
|
||||
"emailError": "Erreur lors de l'envoi de l'email"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Veuillez remplir tous les champs",
|
||||
"invalidEmail": "Veuillez entrer une adresse email valide",
|
||||
"passwordsNotMatch": "Les mots de passe ne correspondent pas",
|
||||
"passwordsNotMatchShort": "Les mots de passe ne correspondent pas",
|
||||
"enterEmail": "Veuillez entrer votre adresse email",
|
||||
"loginFailed": "Échec de la connexion",
|
||||
"registerFailed": "Échec de l'inscription",
|
||||
"googleLoginFailed": "Échec de la connexion Google",
|
||||
"emailExists": "Un utilisateur avec cette adresse email existe déjà. Veuillez utiliser une autre adresse email ou vous connecter."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Inscription réussie. Vous pouvez maintenant vous connecter."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "En cours",
|
||||
"new": "en cours",
|
||||
"pending": "Nouveau",
|
||||
"processing": "En cours",
|
||||
"processing": "en cours",
|
||||
"paid": "Payé",
|
||||
"cancelled": "Annulé",
|
||||
"shipped": "Expédié",
|
||||
"delivered": "Livré",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Annuler la commande"
|
||||
},
|
||||
"noOrders": "Vous n'avez pas encore passé de commandes.",
|
||||
"trackShipment": "Suivre l'envoi",
|
||||
"details": {
|
||||
"title": "Détails de la commande : {{orderId}}",
|
||||
"deliveryAddress": "Adresse de livraison",
|
||||
@@ -36,14 +38,13 @@ export default {
|
||||
"item": "Article",
|
||||
"quantity": "Quantité",
|
||||
"price": "Prix",
|
||||
"vat": "TVA",
|
||||
"total": "Total",
|
||||
"cancelOrder": "Annuler la commande"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Annuler la commande",
|
||||
"message": "Êtes-vous sûr de vouloir annuler cette commande ?",
|
||||
"confirm": "Annuler la commande",
|
||||
"confirm": "Annuler",
|
||||
"cancelling": "Annulation en cours..."
|
||||
},
|
||||
"processing": "La commande est en cours de traitement..."
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Lozinka",
|
||||
"newPassword": "Nova lozinka",
|
||||
"confirmPassword": "Potvrdi lozinku",
|
||||
"forgotPassword": "Zaboravili ste lozinku?",
|
||||
"loginWithGoogle": "Prijavite se putem Googlea",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Pravila privatnosti",
|
||||
"passwordMinLength": "Lozinka mora imati najmanje 8 znakova",
|
||||
"newPasswordMinLength": "Nova lozinka mora imati najmanje 8 znakova",
|
||||
"backToHome": "Natrag na početnu stranicu",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Moj profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Postavke",
|
||||
"adminDashboard": "Admin nadzorna ploča",
|
||||
"adminUsers": "Admin korisnici"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Resetiraj lozinku",
|
||||
"button": "Resetiraj lozinku",
|
||||
"success": "Vaša lozinka je uspješno resetirana! Uskoro ćete biti preusmjereni na prijavu...",
|
||||
"invalidToken": "Nije pronađen valjani token. Molimo koristite link iz vaše e-pošte.",
|
||||
"error": "Pogreška pri resetiranju lozinke",
|
||||
"emailSent": "Link za resetiranje lozinke poslan je na vašu e-mail adresu.",
|
||||
"emailError": "Pogreška pri slanju e-pošte"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Molimo ispunite sva polja",
|
||||
"invalidEmail": "Molimo unesite valjanu e-mail adresu",
|
||||
"passwordsNotMatch": "Lozinke se ne podudaraju",
|
||||
"passwordsNotMatchShort": "Lozinke se ne podudaraju",
|
||||
"enterEmail": "Molimo unesite vašu e-mail adresu",
|
||||
"loginFailed": "Prijava nije uspjela",
|
||||
"registerFailed": "Registracija nije uspjela",
|
||||
"googleLoginFailed": "Prijava putem Googlea nije uspjela",
|
||||
"emailExists": "Korisnik s ovom e-mail adresom već postoji. Molimo koristite drugu e-mail adresu ili se prijavite."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registracija uspješna. Sada se možete prijaviti."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "U tijeku",
|
||||
"new": "u tijeku",
|
||||
"pending": "Novo",
|
||||
"processing": "U tijeku",
|
||||
"processing": "u tijeku",
|
||||
"paid": "Plaćeno",
|
||||
"cancelled": "Otkazano",
|
||||
"shipped": "Poslano",
|
||||
"delivered": "Isporučeno",
|
||||
@@ -23,7 +24,8 @@ export default {
|
||||
"viewDetails": "Pogledaj detalje",
|
||||
"cancelOrder": "Otkaži narudžbu"
|
||||
},
|
||||
"noOrders": "Još niste napravili nijednu narudžbu.",
|
||||
"noOrders": "Još niste izvršili nijednu narudžbu.",
|
||||
"trackShipment": "Prati pošiljku",
|
||||
"details": {
|
||||
"title": "Detalji narudžbe: {{orderId}}",
|
||||
"deliveryAddress": "Adresa dostave",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Artikl",
|
||||
"quantity": "Količina",
|
||||
"price": "Cijena",
|
||||
"vat": "PDV",
|
||||
"total": "Ukupno",
|
||||
"cancelOrder": "Otkaži narudžbu"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Otkaži narudžbu",
|
||||
"message": "Jeste li sigurni da želite otkazati ovu narudžbu?",
|
||||
"confirm": "Otkaži narudžbu",
|
||||
"confirm": "Otkaži",
|
||||
"cancelling": "Otkazivanje..."
|
||||
},
|
||||
"processing": "Narudžba se dovršava...",
|
||||
"processing": "Narudžba se obrađuje..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Jelszó",
|
||||
"newPassword": "Új jelszó",
|
||||
"confirmPassword": "Jelszó megerősítése",
|
||||
"forgotPassword": "Elfelejtett jelszó?",
|
||||
"loginWithGoogle": "Bejelentkezés Google-lal",
|
||||
@@ -13,13 +14,37 @@ export default {
|
||||
"privacyPolicy": "Adatvédelmi szabályzatot",
|
||||
"passwordMinLength": "A jelszónak legalább 8 karakter hosszúnak kell lennie",
|
||||
"newPasswordMinLength": "Az új jelszónak legalább 8 karakter hosszúnak kell lennie",
|
||||
"backToHome": "Vissza a kezdőlapra",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Saját profilom",
|
||||
"myProfile": "Saját profil",
|
||||
"checkout": "Pénztár",
|
||||
"orders": "Rendelések",
|
||||
"settings": "Beállítások",
|
||||
"adminDashboard": "Admin Vezérlőpult",
|
||||
"adminUsers": "Admin Felhasználók"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Jelszó visszaállítása",
|
||||
"button": "Jelszó visszaállítása",
|
||||
"success": "A jelszavad sikeresen visszaállítva! Hamarosan átirányítunk a bejelentkezéshez...",
|
||||
"invalidToken": "Érvényes token nem található. Kérjük, használd az emailedben található linket.",
|
||||
"error": "Hiba történt a jelszó visszaállítása során",
|
||||
"emailSent": "Egy link a jelszó visszaállításához elküldésre került az email címedre.",
|
||||
"emailError": "Hiba történt az email küldése során"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Kérjük, tölts ki minden mezőt",
|
||||
"invalidEmail": "Kérjük, adj meg egy érvényes email címet",
|
||||
"passwordsNotMatch": "A jelszavak nem egyeznek",
|
||||
"passwordsNotMatchShort": "A jelszavak nem egyeznek",
|
||||
"enterEmail": "Kérjük, add meg az email címed",
|
||||
"loginFailed": "Bejelentkezés sikertelen",
|
||||
"registerFailed": "Regisztráció sikertelen",
|
||||
"googleLoginFailed": "Google bejelentkezés sikertelen",
|
||||
"emailExists": "Már létezik felhasználó ezzel az email címmel. Kérjük, használj másik email címet vagy jelentkezz be."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Sikeres regisztráció. Most már bejelentkezhetsz."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "Folyamatban",
|
||||
"new": "feldolgozás alatt",
|
||||
"pending": "Új",
|
||||
"processing": "Folyamatban",
|
||||
"processing": "feldolgozás alatt",
|
||||
"paid": "Fizetve",
|
||||
"cancelled": "Törölve",
|
||||
"shipped": "Kiszállítva",
|
||||
"delivered": "Kézbesítve",
|
||||
"shipped": "Feladva",
|
||||
"delivered": "Kiszállítva",
|
||||
"return": "Visszaküldés",
|
||||
"partialReturn": "Részleges visszaküldés",
|
||||
"partialDelivered": "Részben kézbesítve"
|
||||
"partialDelivered": "Részben kiszállítva"
|
||||
},
|
||||
"table": {
|
||||
"orderNumber": "Rendelésszám",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Rendelés törlése"
|
||||
},
|
||||
"noOrders": "Még nem adott le rendelést.",
|
||||
"trackShipment": "Szállítmány követése",
|
||||
"details": {
|
||||
"title": "Rendelés részletei: {{orderId}}",
|
||||
"deliveryAddress": "Szállítási cím",
|
||||
@@ -36,14 +38,13 @@ export default {
|
||||
"item": "Termék",
|
||||
"quantity": "Mennyiség",
|
||||
"price": "Ár",
|
||||
"vat": "ÁFA",
|
||||
"total": "Összesen",
|
||||
"cancelOrder": "Rendelés törlése"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Rendelés törlése",
|
||||
"message": "Biztosan törölni szeretné ezt a rendelést?",
|
||||
"confirm": "Rendelés törlése",
|
||||
"confirm": "Törlés",
|
||||
"cancelling": "Törlés folyamatban..."
|
||||
},
|
||||
"processing": "A rendelés feldolgozása folyamatban..."
|
||||
|
||||
@@ -5,21 +5,46 @@ export default {
|
||||
"profile": "Profilo",
|
||||
"email": "Email",
|
||||
"password": "Password",
|
||||
"newPassword": "Nuova password",
|
||||
"confirmPassword": "Conferma password",
|
||||
"forgotPassword": "Password dimenticata?",
|
||||
"loginWithGoogle": "Accedi con Google",
|
||||
"or": "O",
|
||||
"privacyAccept": "Cliccando su \"Accedi con Google\" accetto la",
|
||||
"privacyPolicy": "Informativa sulla privacy",
|
||||
"privacyPolicy": "Privacy policy",
|
||||
"passwordMinLength": "La password deve contenere almeno 8 caratteri",
|
||||
"newPasswordMinLength": "La nuova password deve contenere almeno 8 caratteri",
|
||||
"backToHome": "Torna alla homepage",
|
||||
"menu": {
|
||||
"profile": "Profilo",
|
||||
"myProfile": "Il mio profilo",
|
||||
"checkout": "Pagamento",
|
||||
"checkout": "Checkout",
|
||||
"orders": "Ordini",
|
||||
"settings": "Impostazioni",
|
||||
"adminDashboard": "Pannello di amministrazione",
|
||||
"adminUsers": "Utenti amministratori"
|
||||
"adminDashboard": "Admin Dashboard",
|
||||
"adminUsers": "Admin Users"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Reimposta password",
|
||||
"button": "Reimposta password",
|
||||
"success": "La tua password è stata reimpostata con successo! Verrai reindirizzato alla pagina di accesso a breve...",
|
||||
"invalidToken": "Nessun token valido trovato. Per favore usa il link nella tua email.",
|
||||
"error": "Errore durante la reimpostazione della password",
|
||||
"emailSent": "Un link per reimpostare la password è stato inviato al tuo indirizzo email.",
|
||||
"emailError": "Errore nell'invio dell'email"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Per favore compila tutti i campi",
|
||||
"invalidEmail": "Per favore inserisci un indirizzo email valido",
|
||||
"passwordsNotMatch": "Le password non corrispondono",
|
||||
"passwordsNotMatchShort": "Le password non corrispondono",
|
||||
"enterEmail": "Per favore inserisci il tuo indirizzo email",
|
||||
"loginFailed": "Accesso fallito",
|
||||
"registerFailed": "Registrazione fallita",
|
||||
"googleLoginFailed": "Accesso con Google fallito",
|
||||
"emailExists": "Esiste già un utente con questo indirizzo email. Per favore usa un altro indirizzo email o accedi."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registrazione completata con successo. Ora puoi accedere."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "In lavorazione",
|
||||
"new": "in lavorazione",
|
||||
"pending": "Nuovo",
|
||||
"processing": "In lavorazione",
|
||||
"processing": "in lavorazione",
|
||||
"paid": "Pagato",
|
||||
"cancelled": "Annullato",
|
||||
"shipped": "Spedito",
|
||||
"delivered": "Consegnato",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Annulla ordine"
|
||||
},
|
||||
"noOrders": "Non hai ancora effettuato ordini.",
|
||||
"trackShipment": "Traccia spedizione",
|
||||
"details": {
|
||||
"title": "Dettagli ordine: {{orderId}}",
|
||||
"deliveryAddress": "Indirizzo di consegna",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Articolo",
|
||||
"quantity": "Quantità",
|
||||
"price": "Prezzo",
|
||||
"vat": "IVA",
|
||||
"total": "Totale",
|
||||
"cancelOrder": "Annulla ordine"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Annulla ordine",
|
||||
"message": "Sei sicuro di voler annullare questo ordine?",
|
||||
"confirm": "Annulla ordine",
|
||||
"confirm": "Annulla",
|
||||
"cancelling": "Annullamento in corso..."
|
||||
},
|
||||
"processing": "Ordine in elaborazione..."
|
||||
"processing": "Ordine in fase di completamento..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Hasło",
|
||||
"newPassword": "Nowe hasło",
|
||||
"confirmPassword": "Potwierdź hasło",
|
||||
"forgotPassword": "Zapomniałeś hasła?",
|
||||
"loginWithGoogle": "Zaloguj się przez Google",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Politykę prywatności",
|
||||
"passwordMinLength": "Hasło musi mieć co najmniej 8 znaków",
|
||||
"newPasswordMinLength": "Nowe hasło musi mieć co najmniej 8 znaków",
|
||||
"backToHome": "Powrót do strony głównej",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Mój profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Ustawienia",
|
||||
"adminDashboard": "Panel administratora",
|
||||
"adminUsers": "Użytkownicy administratora"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Resetowanie hasła",
|
||||
"button": "Resetuj hasło",
|
||||
"success": "Twoje hasło zostało pomyślnie zresetowane! Wkrótce nastąpi przekierowanie do logowania...",
|
||||
"invalidToken": "Nie znaleziono ważnego tokenu. Proszę użyć linku z e-maila.",
|
||||
"error": "Błąd podczas resetowania hasła",
|
||||
"emailSent": "Link do resetowania hasła został wysłany na Twój adres e-mail.",
|
||||
"emailError": "Błąd podczas wysyłania e-maila"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Proszę wypełnić wszystkie pola",
|
||||
"invalidEmail": "Proszę podać prawidłowy adres e-mail",
|
||||
"passwordsNotMatch": "Hasła nie są zgodne",
|
||||
"passwordsNotMatchShort": "Hasła nie są zgodne",
|
||||
"enterEmail": "Proszę podać swój adres e-mail",
|
||||
"loginFailed": "Logowanie nie powiodło się",
|
||||
"registerFailed": "Rejestracja nie powiodła się",
|
||||
"googleLoginFailed": "Logowanie przez Google nie powiodło się",
|
||||
"emailExists": "Użytkownik z tym adresem e-mail już istnieje. Proszę użyć innego adresu e-mail lub się zalogować."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Rejestracja zakończona sukcesem. Możesz się teraz zalogować."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "W trakcie realizacji",
|
||||
"new": "w trakcie realizacji",
|
||||
"pending": "Nowe",
|
||||
"processing": "W trakcie realizacji",
|
||||
"cancelled": "Anulowano",
|
||||
"shipped": "Wysłano",
|
||||
"delivered": "Dostarczono",
|
||||
"processing": "w trakcie realizacji",
|
||||
"paid": "Opłacone",
|
||||
"cancelled": "Anulowane",
|
||||
"shipped": "Wysłane",
|
||||
"delivered": "Dostarczone",
|
||||
"return": "Zwrot",
|
||||
"partialReturn": "Częściowy zwrot",
|
||||
"partialDelivered": "Częściowo dostarczono"
|
||||
"partialDelivered": "Częściowo dostarczone"
|
||||
},
|
||||
"table": {
|
||||
"orderNumber": "Numer zamówienia",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Anuluj zamówienie"
|
||||
},
|
||||
"noOrders": "Nie złożyłeś jeszcze żadnych zamówień.",
|
||||
"trackShipment": "Śledź przesyłkę",
|
||||
"details": {
|
||||
"title": "Szczegóły zamówienia: {{orderId}}",
|
||||
"deliveryAddress": "Adres dostawy",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Produkt",
|
||||
"quantity": "Ilość",
|
||||
"price": "Cena",
|
||||
"vat": "VAT",
|
||||
"total": "Razem",
|
||||
"cancelOrder": "Anuluj zamówienie"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Anuluj zamówienie",
|
||||
"message": "Czy na pewno chcesz anulować to zamówienie?",
|
||||
"confirm": "Anuluj zamówienie",
|
||||
"confirm": "Anuluj",
|
||||
"cancelling": "Anulowanie..."
|
||||
},
|
||||
"processing": "Zamówienie jest realizowane...",
|
||||
"processing": "Zamówienie jest realizowane..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Parolă",
|
||||
"newPassword": "Parolă nouă",
|
||||
"confirmPassword": "Confirmă parola",
|
||||
"forgotPassword": "Ai uitat parola?",
|
||||
"loginWithGoogle": "Autentifică-te cu Google",
|
||||
@@ -12,14 +13,38 @@ export default {
|
||||
"privacyAccept": "Prin clic pe „Autentifică-te cu Google” accept",
|
||||
"privacyPolicy": "Politica de confidențialitate",
|
||||
"passwordMinLength": "Parola trebuie să aibă cel puțin 8 caractere",
|
||||
"newPasswordMinLength": "Noua parolă trebuie să aibă cel puțin 8 caractere",
|
||||
"newPasswordMinLength": "Parola nouă trebuie să aibă cel puțin 8 caractere",
|
||||
"backToHome": "Înapoi la pagina principală",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Profilul meu",
|
||||
"checkout": "Finalizare comandă",
|
||||
"orders": "Comenzi",
|
||||
"settings": "Setări",
|
||||
"adminDashboard": "Panou de administrare",
|
||||
"adminUsers": "Utilizatori administratori"
|
||||
"adminDashboard": "Panou Admin",
|
||||
"adminUsers": "Utilizatori Admin"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Resetează parola",
|
||||
"button": "Resetează parola",
|
||||
"success": "Parola ta a fost resetată cu succes! Vei fi redirecționat către autentificare în scurt timp...",
|
||||
"invalidToken": "Nu a fost găsit un token valid. Te rugăm să folosești linkul din emailul tău.",
|
||||
"error": "Eroare la resetarea parolei",
|
||||
"emailSent": "Un link pentru resetarea parolei a fost trimis la adresa ta de email.",
|
||||
"emailError": "Eroare la trimiterea emailului"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Te rugăm să completezi toate câmpurile",
|
||||
"invalidEmail": "Te rugăm să introduci o adresă de email validă",
|
||||
"passwordsNotMatch": "Parolele nu coincid",
|
||||
"passwordsNotMatchShort": "Parolele nu coincid",
|
||||
"enterEmail": "Te rugăm să introduci adresa ta de email",
|
||||
"loginFailed": "Autentificare eșuată",
|
||||
"registerFailed": "Înregistrare eșuată",
|
||||
"googleLoginFailed": "Autentificare Google eșuată",
|
||||
"emailExists": "Un utilizator cu această adresă de email există deja. Te rugăm să folosești o altă adresă de email sau să te autentifici."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Înregistrare reușită. Acum te poți autentifica."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,50 +1,51 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "În curs",
|
||||
"pending": "Nou",
|
||||
"processing": "În curs",
|
||||
"cancelled": "Anulat",
|
||||
"shipped": "Expediat",
|
||||
"delivered": "Livrat",
|
||||
"return": "Returnare",
|
||||
"partialReturn": "Returnare parțială",
|
||||
"partialDelivered": "Livrat parțial"
|
||||
"new": "în curs",
|
||||
"pending": "Nou",
|
||||
"processing": "în curs",
|
||||
"paid": "Plătit",
|
||||
"cancelled": "Anulat",
|
||||
"shipped": "Expediat",
|
||||
"delivered": "Livrat",
|
||||
"return": "Returnare",
|
||||
"partialReturn": "Returnare parțială",
|
||||
"partialDelivered": "Livrat parțial"
|
||||
},
|
||||
"table": {
|
||||
"orderNumber": "Număr comandă",
|
||||
"date": "Data",
|
||||
"status": "Status",
|
||||
"items": "Articole",
|
||||
"total": "Total",
|
||||
"actions": "Acțiuni",
|
||||
"viewDetails": "Vezi detalii"
|
||||
"orderNumber": "Număr comandă",
|
||||
"date": "Data",
|
||||
"status": "Status",
|
||||
"items": "Articole",
|
||||
"total": "Total",
|
||||
"actions": "Acțiuni",
|
||||
"viewDetails": "Vezi detalii"
|
||||
},
|
||||
"tooltips": {
|
||||
"viewDetails": "Vezi detalii",
|
||||
"cancelOrder": "Anulează comanda"
|
||||
"viewDetails": "Vezi detalii",
|
||||
"cancelOrder": "Anulează comanda"
|
||||
},
|
||||
"noOrders": "Nu ați plasat încă nicio comandă.",
|
||||
"noOrders": "Nu ați plasat încă nicio comandă.",
|
||||
"trackShipment": "Urmărește expedierea",
|
||||
"details": {
|
||||
"title": "Detalii comandă: {{orderId}}",
|
||||
"deliveryAddress": "Adresa de livrare",
|
||||
"invoiceAddress": "Adresa de facturare",
|
||||
"orderDetails": "Detalii comandă",
|
||||
"deliveryMethod": "Metoda de livrare:",
|
||||
"paymentMethod": "Metoda de plată:",
|
||||
"notSpecified": "Nespecificat",
|
||||
"orderedItems": "Articole comandate",
|
||||
"item": "Articol",
|
||||
"quantity": "Cantitate",
|
||||
"price": "Preț",
|
||||
"vat": "TVA",
|
||||
"total": "Total",
|
||||
"cancelOrder": "Anulează comanda"
|
||||
"title": "Detalii comandă: {{orderId}}",
|
||||
"deliveryAddress": "Adresa de livrare",
|
||||
"invoiceAddress": "Adresa de facturare",
|
||||
"orderDetails": "Detalii comandă",
|
||||
"deliveryMethod": "Metoda de livrare:",
|
||||
"paymentMethod": "Metoda de plată:",
|
||||
"notSpecified": "Nespecificat",
|
||||
"orderedItems": "Articole comandate",
|
||||
"item": "Articol",
|
||||
"quantity": "Cantitate",
|
||||
"price": "Preț",
|
||||
"total": "Total",
|
||||
"cancelOrder": "Anulează comanda"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Anulează comanda",
|
||||
"message": "Sigur doriți să anulați această comandă?",
|
||||
"confirm": "Anulează comanda",
|
||||
"cancelling": "Se anulează..."
|
||||
"title": "Anulează comanda",
|
||||
"message": "Sigur doriți să anulați această comandă?",
|
||||
"confirm": "Anulează",
|
||||
"cancelling": "Se anulează..."
|
||||
},
|
||||
"processing": "Comanda este în curs de finalizare..."
|
||||
"processing": "Comanda este în curs de finalizare..."
|
||||
};
|
||||
|
||||
@@ -5,14 +5,16 @@ export default {
|
||||
"profile": "Профиль",
|
||||
"email": "Электронная почта",
|
||||
"password": "Пароль",
|
||||
"newPassword": "Новый пароль",
|
||||
"confirmPassword": "Подтвердите пароль",
|
||||
"forgotPassword": "Забыли пароль?",
|
||||
"loginWithGoogle": "Войти через Google",
|
||||
"or": "ИЛИ",
|
||||
"privacyAccept": "Нажимая «Войти через Google», я принимаю",
|
||||
"privacyAccept": "Нажимая на \"Войти через Google\", я принимаю",
|
||||
"privacyPolicy": "Политику конфиденциальности",
|
||||
"passwordMinLength": "Пароль должен содержать не менее 8 символов",
|
||||
"newPasswordMinLength": "Новый пароль должен содержать не менее 8 символов",
|
||||
"backToHome": "Вернуться на главную страницу",
|
||||
"menu": {
|
||||
"profile": "Профиль",
|
||||
"myProfile": "Мой профиль",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Настройки",
|
||||
"adminDashboard": "Панель администратора",
|
||||
"adminUsers": "Пользователи администратора"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Сброс пароля",
|
||||
"button": "Сбросить пароль",
|
||||
"success": "Ваш пароль успешно сброшен! Скоро вы будете перенаправлены на страницу входа...",
|
||||
"invalidToken": "Действительный токен не найден. Пожалуйста, используйте ссылку из вашего письма.",
|
||||
"error": "Ошибка при сбросе пароля",
|
||||
"emailSent": "Ссылка для сброса пароля была отправлена на ваш адрес электронной почты.",
|
||||
"emailError": "Ошибка при отправке письма"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Пожалуйста, заполните все поля",
|
||||
"invalidEmail": "Пожалуйста, введите действительный адрес электронной почты",
|
||||
"passwordsNotMatch": "Пароли не совпадают",
|
||||
"passwordsNotMatchShort": "Пароли не совпадают",
|
||||
"enterEmail": "Пожалуйста, введите ваш адрес электронной почты",
|
||||
"loginFailed": "Не удалось войти",
|
||||
"registerFailed": "Не удалось зарегистрироваться",
|
||||
"googleLoginFailed": "Не удалось войти через Google",
|
||||
"emailExists": "Пользователь с таким адресом электронной почты уже существует. Пожалуйста, используйте другой адрес электронной почты или войдите в систему."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Регистрация прошла успешно. Теперь вы можете войти."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "В процессе",
|
||||
"new": "в процессе",
|
||||
"pending": "Новый",
|
||||
"processing": "В процессе",
|
||||
"cancelled": "Отменён",
|
||||
"shipped": "Отправлен",
|
||||
"delivered": "Доставлен",
|
||||
"processing": "в процессе",
|
||||
"paid": "Оплачено",
|
||||
"cancelled": "Отменено",
|
||||
"shipped": "Отправлено",
|
||||
"delivered": "Доставлено",
|
||||
"return": "Возврат",
|
||||
"partialReturn": "Частичный возврат",
|
||||
"partialDelivered": "Частично доставлен"
|
||||
"partialDelivered": "Частично доставлено"
|
||||
},
|
||||
"table": {
|
||||
"orderNumber": "Номер заказа",
|
||||
@@ -23,11 +24,12 @@ export default {
|
||||
"viewDetails": "Просмотреть детали",
|
||||
"cancelOrder": "Отменить заказ"
|
||||
},
|
||||
"noOrders": "Вы ещё не сделали ни одного заказа.",
|
||||
"noOrders": "Вы еще не сделали ни одного заказа.",
|
||||
"trackShipment": "Отследить отправление",
|
||||
"details": {
|
||||
"title": "Детали заказа: {{orderId}}",
|
||||
"deliveryAddress": "Адрес доставки",
|
||||
"invoiceAddress": "Адрес для счёта",
|
||||
"invoiceAddress": "Адрес для счета",
|
||||
"orderDetails": "Детали заказа",
|
||||
"deliveryMethod": "Способ доставки:",
|
||||
"paymentMethod": "Способ оплаты:",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Товар",
|
||||
"quantity": "Количество",
|
||||
"price": "Цена",
|
||||
"vat": "НДС",
|
||||
"total": "Итого",
|
||||
"cancelOrder": "Отменить заказ"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Отмена заказа",
|
||||
"title": "Отменить заказ",
|
||||
"message": "Вы уверены, что хотите отменить этот заказ?",
|
||||
"confirm": "Отменить заказ",
|
||||
"confirm": "Отменить",
|
||||
"cancelling": "Отмена..."
|
||||
},
|
||||
"processing": "Заказ обрабатывается...",
|
||||
"processing": "Заказ обрабатывается..."
|
||||
};
|
||||
|
||||
@@ -5,14 +5,16 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Heslo",
|
||||
"newPassword": "Nové heslo",
|
||||
"confirmPassword": "Potvrdiť heslo",
|
||||
"forgotPassword": "Zabudli ste heslo?",
|
||||
"loginWithGoogle": "Prihlásiť sa cez Google",
|
||||
"or": "ALEBO",
|
||||
"privacyAccept": "Kliknutím na „Prihlásiť sa cez Google“ súhlasím s",
|
||||
"privacyPolicy": "Zásadami ochrany osobných údajov",
|
||||
"privacyPolicy": "zásadami ochrany osobných údajov",
|
||||
"passwordMinLength": "Heslo musí mať aspoň 8 znakov",
|
||||
"newPasswordMinLength": "Nové heslo musí mať aspoň 8 znakov",
|
||||
"backToHome": "Späť na domovskú stránku",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Môj profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Nastavenia",
|
||||
"adminDashboard": "Admin Dashboard",
|
||||
"adminUsers": "Admin Users"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Obnoviť heslo",
|
||||
"button": "Obnoviť heslo",
|
||||
"success": "Vaše heslo bolo úspešne obnovené! Čoskoro budete presmerovaní na prihlásenie...",
|
||||
"invalidToken": "Nenašiel sa platný token. Použite prosím odkaz z vášho e-mailu.",
|
||||
"error": "Chyba pri obnove hesla",
|
||||
"emailSent": "Odkaz na obnovenie hesla bol odoslaný na vašu e-mailovú adresu.",
|
||||
"emailError": "Chyba pri odosielaní e-mailu"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Prosím, vyplňte všetky polia",
|
||||
"invalidEmail": "Zadajte platnú e-mailovú adresu",
|
||||
"passwordsNotMatch": "Heslá sa nezhodujú",
|
||||
"passwordsNotMatchShort": "Heslá sa nezhodujú",
|
||||
"enterEmail": "Zadajte svoju e-mailovú adresu",
|
||||
"loginFailed": "Prihlásenie zlyhalo",
|
||||
"registerFailed": "Registrácia zlyhala",
|
||||
"googleLoginFailed": "Prihlásenie cez Google zlyhalo",
|
||||
"emailExists": "Používateľ s touto e-mailovou adresou už existuje. Použite prosím inú e-mailovú adresu alebo sa prihláste."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registrácia bola úspešná. Teraz sa môžete prihlásiť."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "Prebieha",
|
||||
"new": "v procese",
|
||||
"pending": "Nové",
|
||||
"processing": "Prebieha",
|
||||
"processing": "v procese",
|
||||
"paid": "Zaplatené",
|
||||
"cancelled": "Zrušené",
|
||||
"shipped": "Odoslané",
|
||||
"delivered": "Doručené",
|
||||
@@ -15,7 +16,7 @@ export default {
|
||||
"date": "Dátum",
|
||||
"status": "Stav",
|
||||
"items": "Položky",
|
||||
"total": "Spolu",
|
||||
"total": "Celkom",
|
||||
"actions": "Akcie",
|
||||
"viewDetails": "Zobraziť detaily"
|
||||
},
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Zrušiť objednávku"
|
||||
},
|
||||
"noOrders": "Ešte ste neuskutočnili žiadne objednávky.",
|
||||
"trackShipment": "Sledovať zásielku",
|
||||
"details": {
|
||||
"title": "Detaily objednávky: {{orderId}}",
|
||||
"deliveryAddress": "Dodacia adresa",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Položka",
|
||||
"quantity": "Množstvo",
|
||||
"price": "Cena",
|
||||
"vat": "DPH",
|
||||
"total": "Spolu",
|
||||
"cancelOrder": "Zrušiť objednávku"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Zrušiť objednávku",
|
||||
"message": "Naozaj chcete zrušiť túto objednávku?",
|
||||
"confirm": "Zrušiť objednávku",
|
||||
"message": "Ste si istý, že chcete zrušiť túto objednávku?",
|
||||
"confirm": "Zrušiť",
|
||||
"cancelling": "Zrušovanie..."
|
||||
},
|
||||
"processing": "Objednávka sa dokončuje..."
|
||||
"processing": "Objednávka sa spracováva..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "E-pošta",
|
||||
"password": "Geslo",
|
||||
"newPassword": "Novo geslo",
|
||||
"confirmPassword": "Potrdi geslo",
|
||||
"forgotPassword": "Ste pozabili geslo?",
|
||||
"loginWithGoogle": "Prijava z Google",
|
||||
@@ -13,13 +14,37 @@ export default {
|
||||
"privacyPolicy": "Pravilnik o zasebnosti",
|
||||
"passwordMinLength": "Geslo mora biti dolgo vsaj 8 znakov",
|
||||
"newPasswordMinLength": "Novo geslo mora biti dolgo vsaj 8 znakov",
|
||||
"backToHome": "Nazaj na domačo stran",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Moj profil",
|
||||
"checkout": "Zaključek nakupa",
|
||||
"orders": "Naročila",
|
||||
"settings": "Nastavitve",
|
||||
"adminDashboard": "Nadzorna plošča administratorja",
|
||||
"adminUsers": "Administratorji"
|
||||
"adminDashboard": "Administratorska nadzorna plošča",
|
||||
"adminUsers": "Administratorski uporabniki"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Ponastavi geslo",
|
||||
"button": "Ponastavi geslo",
|
||||
"success": "Vaše geslo je bilo uspešno ponastavljeno! Kmalu boste preusmerjeni na prijavo...",
|
||||
"invalidToken": "Ni najden veljaven žeton. Prosimo, uporabite povezavo iz vašega e-poštnega sporočila.",
|
||||
"error": "Napaka pri ponastavitvi gesla",
|
||||
"emailSent": "Povezava za ponastavitev gesla je bila poslana na vaš e-poštni naslov.",
|
||||
"emailError": "Napaka pri pošiljanju e-pošte"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Prosimo, izpolnite vsa polja",
|
||||
"invalidEmail": "Prosimo, vnesite veljaven e-poštni naslov",
|
||||
"passwordsNotMatch": "Gesli se ne ujemata",
|
||||
"passwordsNotMatchShort": "Gesli se ne ujemata",
|
||||
"enterEmail": "Prosimo, vnesite vaš e-poštni naslov",
|
||||
"loginFailed": "Prijava ni uspela",
|
||||
"registerFailed": "Registracija ni uspela",
|
||||
"googleLoginFailed": "Prijava z Google ni uspela",
|
||||
"emailExists": "Uporabnik s tem e-poštnim naslovom že obstaja. Prosimo, uporabite drug e-poštni naslov ali se prijavite."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registracija je bila uspešna. Zdaj se lahko prijavite."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "V teku",
|
||||
"new": "v teku",
|
||||
"pending": "Novo",
|
||||
"processing": "V teku",
|
||||
"processing": "v teku",
|
||||
"paid": "Plačano",
|
||||
"cancelled": "Preklicano",
|
||||
"shipped": "Poslano",
|
||||
"delivered": "Dostavljeno",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Prekliči naročilo"
|
||||
},
|
||||
"noOrders": "Še niste oddali nobenega naročila.",
|
||||
"trackShipment": "Sledi pošiljki",
|
||||
"details": {
|
||||
"title": "Podrobnosti naročila: {{orderId}}",
|
||||
"deliveryAddress": "Naslov za dostavo",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Izdelek",
|
||||
"quantity": "Količina",
|
||||
"price": "Cena",
|
||||
"vat": "DDV",
|
||||
"total": "Skupaj",
|
||||
"cancelOrder": "Prekliči naročilo"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Prekliči naročilo",
|
||||
"message": "Ste prepričani, da želite preklicati to naročilo?",
|
||||
"confirm": "Prekliči naročilo",
|
||||
"confirm": "Prekliči",
|
||||
"cancelling": "Preklicujem..."
|
||||
},
|
||||
"processing": "Naročilo se zaključuje...",
|
||||
"processing": "Naročilo se zaključuje..."
|
||||
};
|
||||
|
||||
@@ -5,21 +5,46 @@ export default {
|
||||
"profile": "Profili",
|
||||
"email": "Email",
|
||||
"password": "Fjalëkalimi",
|
||||
"newPassword": "Fjalëkalim i ri",
|
||||
"confirmPassword": "Konfirmo fjalëkalimin",
|
||||
"forgotPassword": "Keni harruar fjalëkalimin?",
|
||||
"loginWithGoogle": "Hyr me Google",
|
||||
"or": "OSE",
|
||||
"privacyAccept": "Duke klikuar \"Hyr me Google\" pranoj",
|
||||
"privacyPolicy": "Politikën e Privatësisë",
|
||||
"privacyAccept": "Duke klikuar në \"Hyr me Google\" unë pranoj",
|
||||
"privacyPolicy": "Politikën e privatësisë",
|
||||
"passwordMinLength": "Fjalëkalimi duhet të ketë të paktën 8 karaktere",
|
||||
"newPasswordMinLength": "Fjalëkalimi i ri duhet të ketë të paktën 8 karaktere",
|
||||
"backToHome": "Kthehu në faqen kryesore",
|
||||
"menu": {
|
||||
"profile": "Profili",
|
||||
"myProfile": "Profili im",
|
||||
"checkout": "Përfundimi i porosisë",
|
||||
"orders": "Porositë",
|
||||
"settings": "Cilësimet",
|
||||
"adminDashboard": "Paneli i Administratorit",
|
||||
"adminUsers": "Përdoruesit e Administratorit"
|
||||
"adminDashboard": "Paneli i administratorit",
|
||||
"adminUsers": "Përdoruesit e administratorit"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Rivendos fjalëkalimin",
|
||||
"button": "Rivendos fjalëkalimin",
|
||||
"success": "Fjalëkalimi juaj u rivendos me sukses! Do të ridrejtoheni për t'u futur së shpejti...",
|
||||
"invalidToken": "Nuk u gjet asnjë token i vlefshëm. Ju lutemi përdorni lidhjen nga emaili juaj.",
|
||||
"error": "Gabim gjatë rivendosjes së fjalëkalimit",
|
||||
"emailSent": "Një lidhje për rivendosjen e fjalëkalimit është dërguar në adresën tuaj të emailit.",
|
||||
"emailError": "Gabim gjatë dërgimit të emailit"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Ju lutemi plotësoni të gjitha fushat",
|
||||
"invalidEmail": "Ju lutemi shkruani një adresë emaili të vlefshme",
|
||||
"passwordsNotMatch": "Fjalëkalimet nuk përputhen",
|
||||
"passwordsNotMatchShort": "Fjalëkalimet nuk përputhen",
|
||||
"enterEmail": "Ju lutemi shkruani adresën tuaj të emailit",
|
||||
"loginFailed": "Hyrja dështoi",
|
||||
"registerFailed": "Regjistrimi dështoi",
|
||||
"googleLoginFailed": "Hyrja me Google dështoi",
|
||||
"emailExists": "Një përdorues me këtë adresë emaili ekziston tashmë. Ju lutemi përdorni një adresë tjetër emaili ose hyni."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Regjistrimi u krye me sukses. Tani mund të hyni."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "Në proces",
|
||||
"new": "në proces",
|
||||
"pending": "E re",
|
||||
"processing": "Në proces",
|
||||
"processing": "në proces",
|
||||
"paid": "E paguar",
|
||||
"cancelled": "Anuluar",
|
||||
"shipped": "Dërguar",
|
||||
"delivered": "Dorëzuar",
|
||||
"return": "Kthim",
|
||||
"partialReturn": "Kthim pjesërisht",
|
||||
"partialReturn": "Kthim i pjesshëm",
|
||||
"partialDelivered": "Dorëzuar pjesërisht"
|
||||
},
|
||||
"table": {
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Anulo porosinë"
|
||||
},
|
||||
"noOrders": "Nuk keni bërë ende asnjë porosi.",
|
||||
"trackShipment": "Ndjek dërgesën",
|
||||
"details": {
|
||||
"title": "Detajet e porosisë: {{orderId}}",
|
||||
"deliveryAddress": "Adresa e dorëzimit",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Artikulli",
|
||||
"quantity": "Sasia",
|
||||
"price": "Çmimi",
|
||||
"vat": "TVSH",
|
||||
"total": "Totali",
|
||||
"cancelOrder": "Anulo porosinë"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Anulo Porosinë",
|
||||
"title": "Anulo porosinë",
|
||||
"message": "A jeni i sigurt që dëshironi të anuloni këtë porosi?",
|
||||
"confirm": "Anulo Porosinë",
|
||||
"confirm": "Anulo",
|
||||
"cancelling": "Duke anuluar..."
|
||||
},
|
||||
"processing": "Porosia po përpunohet...",
|
||||
"processing": "Porosia po përpunohet..."
|
||||
};
|
||||
|
||||
@@ -5,14 +5,16 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "Email",
|
||||
"password": "Lozinka",
|
||||
"newPassword": "Nova lozinka",
|
||||
"confirmPassword": "Potvrdi lozinku",
|
||||
"forgotPassword": "Zaboravili ste lozinku?",
|
||||
"loginWithGoogle": "Prijavite se sa Google-om",
|
||||
"loginWithGoogle": "Prijavite se putem Google-a",
|
||||
"or": "ILI",
|
||||
"privacyAccept": "Klikom na \"Prijavite se sa Google-om\" prihvatam",
|
||||
"privacyAccept": "Klikom na \"Prijavite se putem Google-a\" prihvatam",
|
||||
"privacyPolicy": "Politiku privatnosti",
|
||||
"passwordMinLength": "Lozinka mora imati najmanje 8 karaktera",
|
||||
"newPasswordMinLength": "Nova lozinka mora imati najmanje 8 karaktera",
|
||||
"backToHome": "Nazad na početnu stranicu",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Moj profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Podešavanja",
|
||||
"adminDashboard": "Admin kontrolna tabla",
|
||||
"adminUsers": "Admin korisnici"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Resetovanje lozinke",
|
||||
"button": "Resetuj lozinku",
|
||||
"success": "Vaša lozinka je uspešno resetovana! Uskoro ćete biti preusmereni na prijavu...",
|
||||
"invalidToken": "Nije pronađen važeći token. Molimo koristite link iz vaše email poruke.",
|
||||
"error": "Greška pri resetovanju lozinke",
|
||||
"emailSent": "Link za resetovanje lozinke je poslat na vašu email adresu.",
|
||||
"emailError": "Greška pri slanju email-a"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Molimo popunite sva polja",
|
||||
"invalidEmail": "Molimo unesite validnu email adresu",
|
||||
"passwordsNotMatch": "Lozinke se ne poklapaju",
|
||||
"passwordsNotMatchShort": "Lozinke se ne poklapaju",
|
||||
"enterEmail": "Molimo unesite vašu email adresu",
|
||||
"loginFailed": "Prijava nije uspela",
|
||||
"registerFailed": "Registracija nije uspela",
|
||||
"googleLoginFailed": "Prijava putem Google-a nije uspela",
|
||||
"emailExists": "Korisnik sa ovom email adresom već postoji. Molimo koristite drugu email adresu ili se prijavite."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registracija uspešna. Sada se možete prijaviti."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "U toku",
|
||||
"new": "u toku",
|
||||
"pending": "Novo",
|
||||
"processing": "U toku",
|
||||
"processing": "u toku",
|
||||
"paid": "Plaćeno",
|
||||
"cancelled": "Otkazano",
|
||||
"shipped": "Poslato",
|
||||
"delivered": "Isporučeno",
|
||||
"return": "Povraćaj",
|
||||
"partialReturn": "Delimični povraćaj",
|
||||
"return": "Povrat",
|
||||
"partialReturn": "Delimični povrat",
|
||||
"partialDelivered": "Delimično isporučeno"
|
||||
},
|
||||
"table": {
|
||||
@@ -23,7 +24,8 @@ export default {
|
||||
"viewDetails": "Pogledaj detalje",
|
||||
"cancelOrder": "Otkaži porudžbinu"
|
||||
},
|
||||
"noOrders": "Još uvek niste napravili nijednu porudžbinu.",
|
||||
"noOrders": "Još niste napravili nijednu porudžbinu.",
|
||||
"trackShipment": "Prati pošiljku",
|
||||
"details": {
|
||||
"title": "Detalji porudžbine: {{orderId}}",
|
||||
"deliveryAddress": "Adresa za isporuku",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Artikal",
|
||||
"quantity": "Količina",
|
||||
"price": "Cena",
|
||||
"vat": "PDV",
|
||||
"total": "Ukupno",
|
||||
"cancelOrder": "Otkaži porudžbinu"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Otkaži porudžbinu",
|
||||
"message": "Da li ste sigurni da želite da otkažete ovu porudžbinu?",
|
||||
"confirm": "Otkaži porudžbinu",
|
||||
"cancelling": "Otkazivanje..."
|
||||
"confirm": "Otkaži",
|
||||
"cancelling": "Otkaživanje..."
|
||||
},
|
||||
"processing": "Porudžbina se obrađuje...",
|
||||
"processing": "Porudžbina se obrađuje..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Profil",
|
||||
"email": "E-post",
|
||||
"password": "Lösenord",
|
||||
"newPassword": "Nytt lösenord",
|
||||
"confirmPassword": "Bekräfta lösenord",
|
||||
"forgotPassword": "Glömt lösenord?",
|
||||
"loginWithGoogle": "Logga in med Google",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Integritetspolicy",
|
||||
"passwordMinLength": "Lösenordet måste vara minst 8 tecken långt",
|
||||
"newPasswordMinLength": "Det nya lösenordet måste vara minst 8 tecken långt",
|
||||
"backToHome": "Tillbaka till startsidan",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Min profil",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Inställningar",
|
||||
"adminDashboard": "Admin Dashboard",
|
||||
"adminUsers": "Admin Users"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Återställ lösenord",
|
||||
"button": "Återställ lösenord",
|
||||
"success": "Ditt lösenord har återställts! Du kommer snart att omdirigeras till inloggningen...",
|
||||
"invalidToken": "Ingen giltig token hittades. Vänligen använd länken från ditt e-postmeddelande.",
|
||||
"error": "Fel vid återställning av lösenord",
|
||||
"emailSent": "En länk för att återställa ditt lösenord har skickats till din e-postadress.",
|
||||
"emailError": "Fel vid sändning av e-post"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Vänligen fyll i alla fält",
|
||||
"invalidEmail": "Ange en giltig e-postadress",
|
||||
"passwordsNotMatch": "Lösenorden matchar inte",
|
||||
"passwordsNotMatchShort": "Lösenorden matchar inte",
|
||||
"enterEmail": "Ange din e-postadress",
|
||||
"loginFailed": "Inloggning misslyckades",
|
||||
"registerFailed": "Registrering misslyckades",
|
||||
"googleLoginFailed": "Google-inloggning misslyckades",
|
||||
"emailExists": "En användare med denna e-postadress finns redan. Vänligen använd en annan e-postadress eller logga in."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Registreringen lyckades. Du kan nu logga in."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "Pågående",
|
||||
"new": "pågående",
|
||||
"pending": "Ny",
|
||||
"processing": "Pågående",
|
||||
"processing": "pågående",
|
||||
"paid": "Betald",
|
||||
"cancelled": "Avbruten",
|
||||
"shipped": "Skickad",
|
||||
"delivered": "Levererad",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Avbryt order"
|
||||
},
|
||||
"noOrders": "Du har inte lagt några beställningar än.",
|
||||
"trackShipment": "Spåra försändelse",
|
||||
"details": {
|
||||
"title": "Orderdetaljer: {{orderId}}",
|
||||
"deliveryAddress": "Leveransadress",
|
||||
@@ -36,14 +38,13 @@ export default {
|
||||
"item": "Artikel",
|
||||
"quantity": "Antal",
|
||||
"price": "Pris",
|
||||
"vat": "Moms",
|
||||
"total": "Totalt",
|
||||
"cancelOrder": "Avbryt order"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Avbryt order",
|
||||
"message": "Är du säker på att du vill avbryta denna order?",
|
||||
"confirm": "Avbryt order",
|
||||
"confirm": "Avbryt",
|
||||
"cancelling": "Avbryter..."
|
||||
},
|
||||
"processing": "Ordern behandlas..."
|
||||
|
||||
@@ -4,15 +4,17 @@ export default {
|
||||
"logout": "Çıkış Yap",
|
||||
"profile": "Profil",
|
||||
"email": "E-posta",
|
||||
"password": "Şifre",
|
||||
"confirmPassword": "Şifreyi Onayla",
|
||||
"forgotPassword": "Şifrenizi mi unuttunuz?",
|
||||
"password": "Parola",
|
||||
"newPassword": "Yeni parola",
|
||||
"confirmPassword": "Parolayı onayla",
|
||||
"forgotPassword": "Parolanızı mı unuttunuz?",
|
||||
"loginWithGoogle": "Google ile giriş yap",
|
||||
"or": "VEYA",
|
||||
"privacyAccept": "\"Google ile giriş yap\" butonuna tıklayarak",
|
||||
"privacyPolicy": "Gizlilik Politikasını",
|
||||
"passwordMinLength": "Şifre en az 8 karakter uzunluğunda olmalıdır",
|
||||
"newPasswordMinLength": "Yeni şifre en az 8 karakter uzunluğunda olmalıdır",
|
||||
"privacyPolicy": "Gizlilik politikasını",
|
||||
"passwordMinLength": "Parola en az 8 karakter uzunluğunda olmalıdır",
|
||||
"newPasswordMinLength": "Yeni parola en az 8 karakter uzunluğunda olmalıdır",
|
||||
"backToHome": "Ana sayfaya dön",
|
||||
"menu": {
|
||||
"profile": "Profil",
|
||||
"myProfile": "Profilim",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Ayarlar",
|
||||
"adminDashboard": "Yönetici Paneli",
|
||||
"adminUsers": "Yönetici Kullanıcılar"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Parolayı sıfırla",
|
||||
"button": "Parolayı sıfırla",
|
||||
"success": "Parolanız başarıyla sıfırlandı! Kısa süre içinde giriş sayfasına yönlendirileceksiniz...",
|
||||
"invalidToken": "Geçerli bir token bulunamadı. Lütfen e-postanızdaki bağlantıyı kullanın.",
|
||||
"error": "Parola sıfırlama hatası",
|
||||
"emailSent": "Parolanızı sıfırlamak için bir bağlantı e-posta adresinize gönderildi.",
|
||||
"emailError": "E-posta gönderme hatası"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Lütfen tüm alanları doldurun",
|
||||
"invalidEmail": "Lütfen geçerli bir e-posta adresi girin",
|
||||
"passwordsNotMatch": "Parolalar eşleşmiyor",
|
||||
"passwordsNotMatchShort": "Parolalar eşleşmiyor",
|
||||
"enterEmail": "Lütfen e-posta adresinizi girin",
|
||||
"loginFailed": "Giriş başarısız",
|
||||
"registerFailed": "Kayıt başarısız",
|
||||
"googleLoginFailed": "Google ile giriş başarısız",
|
||||
"emailExists": "Bu e-posta adresiyle zaten bir kullanıcı mevcut. Lütfen başka bir e-posta adresi kullanın veya giriş yapın."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Kayıt başarılı. Artık giriş yapabilirsiniz."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "Devam ediyor",
|
||||
"new": "işlemde",
|
||||
"pending": "Yeni",
|
||||
"processing": "Devam ediyor",
|
||||
"processing": "işlemde",
|
||||
"paid": "Ödendi",
|
||||
"cancelled": "İptal edildi",
|
||||
"shipped": "Gönderildi",
|
||||
"delivered": "Teslim edildi",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Siparişi iptal et"
|
||||
},
|
||||
"noOrders": "Henüz sipariş vermediniz.",
|
||||
"trackShipment": "Gönderiyi takip et",
|
||||
"details": {
|
||||
"title": "Sipariş detayları: {{orderId}}",
|
||||
"deliveryAddress": "Teslimat adresi",
|
||||
@@ -31,20 +33,19 @@ export default {
|
||||
"orderDetails": "Sipariş detayları",
|
||||
"deliveryMethod": "Teslimat yöntemi:",
|
||||
"paymentMethod": "Ödeme yöntemi:",
|
||||
"notSpecified": "Belirtilmemiş",
|
||||
"notSpecified": "Belirtilmedi",
|
||||
"orderedItems": "Sipariş edilen ürünler",
|
||||
"item": "Ürün",
|
||||
"quantity": "Adet",
|
||||
"quantity": "Miktar",
|
||||
"price": "Fiyat",
|
||||
"vat": "KDV",
|
||||
"total": "Toplam",
|
||||
"cancelOrder": "Siparişi iptal et"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Siparişi İptal Et",
|
||||
"title": "Siparişi iptal et",
|
||||
"message": "Bu siparişi iptal etmek istediğinizden emin misiniz?",
|
||||
"confirm": "Siparişi İptal Et",
|
||||
"confirm": "İptal et",
|
||||
"cancelling": "İptal ediliyor..."
|
||||
},
|
||||
"processing": "Sipariş tamamlanıyor...",
|
||||
"processing": "Sipariş tamamlanıyor..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "Профіль",
|
||||
"email": "Електронна пошта",
|
||||
"password": "Пароль",
|
||||
"newPassword": "Новий пароль",
|
||||
"confirmPassword": "Підтвердити пароль",
|
||||
"forgotPassword": "Забули пароль?",
|
||||
"loginWithGoogle": "Увійти через Google",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "Політику конфіденційності",
|
||||
"passwordMinLength": "Пароль повинен містити щонайменше 8 символів",
|
||||
"newPasswordMinLength": "Новий пароль повинен містити щонайменше 8 символів",
|
||||
"backToHome": "Повернутися на головну сторінку",
|
||||
"menu": {
|
||||
"profile": "Профіль",
|
||||
"myProfile": "Мій профіль",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "Налаштування",
|
||||
"adminDashboard": "Панель адміністратора",
|
||||
"adminUsers": "Адміністратори"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "Скинути пароль",
|
||||
"button": "Скинути пароль",
|
||||
"success": "Ваш пароль успішно скинуто! Незабаром ви будете перенаправлені для входу...",
|
||||
"invalidToken": "Дійсний токен не знайдено. Будь ласка, використовуйте посилання з вашої електронної пошти.",
|
||||
"error": "Помилка при скиданні пароля",
|
||||
"emailSent": "Посилання для скидання пароля надіслано на вашу електронну адресу.",
|
||||
"emailError": "Помилка надсилання електронної пошти"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "Будь ласка, заповніть усі поля",
|
||||
"invalidEmail": "Будь ласка, введіть дійсну електронну адресу",
|
||||
"passwordsNotMatch": "Паролі не співпадають",
|
||||
"passwordsNotMatchShort": "Паролі не співпадають",
|
||||
"enterEmail": "Будь ласка, введіть вашу електронну адресу",
|
||||
"loginFailed": "Не вдалося увійти",
|
||||
"registerFailed": "Не вдалося зареєструватися",
|
||||
"googleLoginFailed": "Не вдалося увійти через Google",
|
||||
"emailExists": "Користувач з цією електронною адресою вже існує. Будь ласка, використовуйте іншу адресу або увійдіть."
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "Реєстрація успішна. Тепер ви можете увійти."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
"status": {
|
||||
"new": "В процесі",
|
||||
"new": "в процесі",
|
||||
"pending": "Новий",
|
||||
"processing": "В процесі",
|
||||
"processing": "в процесі",
|
||||
"paid": "Оплачено",
|
||||
"cancelled": "Скасовано",
|
||||
"shipped": "Відправлено",
|
||||
"delivered": "Доставлено",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"cancelOrder": "Скасувати замовлення"
|
||||
},
|
||||
"noOrders": "Ви ще не робили замовлень.",
|
||||
"trackShipment": "Відстежити відправлення",
|
||||
"details": {
|
||||
"title": "Деталі замовлення: {{orderId}}",
|
||||
"deliveryAddress": "Адреса доставки",
|
||||
@@ -36,15 +38,14 @@ export default {
|
||||
"item": "Товар",
|
||||
"quantity": "Кількість",
|
||||
"price": "Ціна",
|
||||
"vat": "ПДВ",
|
||||
"total": "Всього",
|
||||
"cancelOrder": "Скасувати замовлення"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "Скасувати замовлення",
|
||||
"message": "Ви впевнені, що хочете скасувати це замовлення?",
|
||||
"confirm": "Скасувати замовлення",
|
||||
"cancelling": "Скасування..."
|
||||
"confirm": "Скасувати",
|
||||
"cancelling": "Скасовується..."
|
||||
},
|
||||
"processing": "Замовлення обробляється...",
|
||||
"processing": "Замовлення обробляється..."
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
"profile": "个人资料",
|
||||
"email": "电子邮件",
|
||||
"password": "密码",
|
||||
"newPassword": "新密码",
|
||||
"confirmPassword": "确认密码",
|
||||
"forgotPassword": "忘记密码?",
|
||||
"loginWithGoogle": "使用 Google 登录",
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
"privacyPolicy": "隐私政策",
|
||||
"passwordMinLength": "密码长度至少为8个字符",
|
||||
"newPasswordMinLength": "新密码长度至少为8个字符",
|
||||
"backToHome": "返回首页",
|
||||
"menu": {
|
||||
"profile": "个人资料",
|
||||
"myProfile": "我的资料",
|
||||
@@ -21,5 +23,28 @@ export default {
|
||||
"settings": "设置",
|
||||
"adminDashboard": "管理员面板",
|
||||
"adminUsers": "管理员用户"
|
||||
},
|
||||
"resetPassword": {
|
||||
"title": "重置密码",
|
||||
"button": "重置密码",
|
||||
"success": "您的密码已成功重置!您将很快被重定向到登录页面...",
|
||||
"invalidToken": "未找到有效的令牌。请使用您邮箱中的链接。",
|
||||
"error": "重置密码时出错",
|
||||
"emailSent": "重置密码的链接已发送到您的电子邮件地址。",
|
||||
"emailError": "发送电子邮件时出错"
|
||||
},
|
||||
"errors": {
|
||||
"fillAllFields": "请填写所有字段",
|
||||
"invalidEmail": "请输入有效的电子邮件地址",
|
||||
"passwordsNotMatch": "密码不匹配",
|
||||
"passwordsNotMatchShort": "密码不匹配",
|
||||
"enterEmail": "请输入您的电子邮件地址",
|
||||
"loginFailed": "登录失败",
|
||||
"registerFailed": "注册失败",
|
||||
"googleLoginFailed": "Google 登录失败",
|
||||
"emailExists": "该电子邮件地址已被注册。请使用其他电子邮件地址或登录。"
|
||||
},
|
||||
"success": {
|
||||
"registerComplete": "注册成功。您现在可以登录。"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
"new": "进行中",
|
||||
"pending": "新订单",
|
||||
"processing": "进行中",
|
||||
"paid": "已付款",
|
||||
"cancelled": "已取消",
|
||||
"shipped": "已发货",
|
||||
"delivered": "已送达",
|
||||
@@ -23,27 +24,27 @@ export default {
|
||||
"viewDetails": "查看详情",
|
||||
"cancelOrder": "取消订单"
|
||||
},
|
||||
"noOrders": "您尚未下过任何订单。",
|
||||
"noOrders": "您还没有下过任何订单。",
|
||||
"trackShipment": "跟踪发货",
|
||||
"details": {
|
||||
"title": "订单详情: {{orderId}}",
|
||||
"deliveryAddress": "收货地址",
|
||||
"invoiceAddress": "发票地址",
|
||||
"orderDetails": "订单详情",
|
||||
"deliveryMethod": "配送方式:",
|
||||
"paymentMethod": "支付方式:",
|
||||
"deliveryMethod": "配送方式:",
|
||||
"paymentMethod": "支付方式:",
|
||||
"notSpecified": "未指定",
|
||||
"orderedItems": "订购商品",
|
||||
"item": "商品",
|
||||
"quantity": "数量",
|
||||
"price": "价格",
|
||||
"vat": "增值税",
|
||||
"total": "总计",
|
||||
"cancelOrder": "取消订单"
|
||||
},
|
||||
"cancelConfirm": {
|
||||
"title": "取消订单",
|
||||
"message": "您确定要取消此订单吗?",
|
||||
"confirm": "取消订单",
|
||||
"confirm": "取消",
|
||||
"cancelling": "正在取消..."
|
||||
},
|
||||
"processing": "订单正在处理..."
|
||||
|
||||
231
src/pages/CategoriesPage.js
Normal file
231
src/pages/CategoriesPage.js
Normal file
@@ -0,0 +1,231 @@
|
||||
import React, { Component } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import LegalPage from './LegalPage.js';
|
||||
import CategoryBox from '../components/CategoryBox.js';
|
||||
import { withI18n } from '../i18n/withTranslation.js';
|
||||
|
||||
// Helper function to recursively collect all categories from the tree
|
||||
const collectAllCategories = (categoryNode, categories = [], level = 0) => {
|
||||
if (!categoryNode) return categories;
|
||||
|
||||
// Add current category (skip root category 209)
|
||||
if (categoryNode.id !== 209 && categoryNode.seoName) {
|
||||
categories.push({
|
||||
id: categoryNode.id,
|
||||
name: categoryNode.name,
|
||||
seoName: categoryNode.seoName,
|
||||
level: level
|
||||
});
|
||||
}
|
||||
|
||||
// Recursively add children
|
||||
if (categoryNode.children) {
|
||||
for (const child of categoryNode.children) {
|
||||
collectAllCategories(child, categories, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
// Check for cached data - handle both browser and prerender environments
|
||||
const getProductCache = () => {
|
||||
if (typeof window !== "undefined" && window.productCache) {
|
||||
return window.productCache;
|
||||
}
|
||||
if (
|
||||
typeof global !== "undefined" &&
|
||||
global.window &&
|
||||
global.window.productCache
|
||||
) {
|
||||
return global.window.productCache;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Initialize categories from cache if available (for prerendering)
|
||||
const initializeCategoryTree = (language = 'de') => {
|
||||
// Try synchronous get from service first if available
|
||||
if (typeof window !== "undefined" && window.categoryService) {
|
||||
const syncData = window.categoryService.getSync(209, language);
|
||||
if (syncData) return syncData;
|
||||
}
|
||||
|
||||
const productCache = getProductCache();
|
||||
// Fallback to productCache checks (mostly for prerender context if service isn't init)
|
||||
const cacheKey = `categoryTree_209_${language}`; // Note: Service uses simpler keys, might mismatch if strictly relying on this
|
||||
|
||||
// Check old style cache just in case
|
||||
if (productCache && productCache[cacheKey]) {
|
||||
const cached = productCache[cacheKey];
|
||||
if (cached.categoryTree) return cached.categoryTree;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
class CategoriesPage extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// Use languageContext if available, otherwise fallback to i18n or 'de'
|
||||
const currentLanguage = props.languageContext?.currentLanguage || props.i18n?.language || 'de';
|
||||
const initialTree = initializeCategoryTree(currentLanguage);
|
||||
|
||||
console.log("CategoriesPage constructor: currentLanguage =", currentLanguage);
|
||||
|
||||
this.state = {
|
||||
categoryTree: initialTree,
|
||||
loading: !initialTree
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n?.language || 'de';
|
||||
|
||||
// If we don't have data yet, or if we want to ensure freshness/socket connection
|
||||
if (!this.state.categoryTree) {
|
||||
this.fetchCategories(currentLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n?.language || 'de';
|
||||
const prevLanguage = prevProps.languageContext?.currentLanguage || prevProps.i18n?.language || 'de';
|
||||
|
||||
if (currentLanguage !== prevLanguage) {
|
||||
console.log(`CategoriesPage: Language changed from ${prevLanguage} to ${currentLanguage}. Refetching.`);
|
||||
this.setState({ loading: true, categoryTree: [] }); // Clear tree to force re-render/loading state
|
||||
this.fetchCategories(currentLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
fetchCategories = (language) => {
|
||||
// Use categoryService which handles caching and translated vs untranslated responses correctly
|
||||
console.log(`CategoriesPage: Fetching categories for ${language} using categoryService`);
|
||||
|
||||
window.categoryService.get(209, language).then((tree) => {
|
||||
if (tree) {
|
||||
this.setState({
|
||||
categoryTree: tree,
|
||||
loading: false
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to fetch categories via service');
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error("Error in categoryService:", err);
|
||||
this.setState({ loading: false });
|
||||
});
|
||||
};
|
||||
|
||||
renderLevel1Section = (l1Node) => {
|
||||
// Collect all descendants (excluding the L1 node itself, which collectAllCategories would include first)
|
||||
const descendants = collectAllCategories(l1Node).slice(1);
|
||||
|
||||
return (
|
||||
<Paper
|
||||
key={l1Node.id}
|
||||
elevation={1}
|
||||
sx={{
|
||||
p: 2,
|
||||
mb: 3,
|
||||
display: 'flex',
|
||||
flexDirection: { xs: 'column', md: 'row' },
|
||||
alignItems: { xs: 'flex-start', md: 'flex-start' },
|
||||
gap: 3
|
||||
}}
|
||||
>
|
||||
{/* Level 1 Header/Box */}
|
||||
<Box sx={{
|
||||
minWidth: '150px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: 1
|
||||
}}>
|
||||
<CategoryBox
|
||||
id={l1Node.id}
|
||||
name={l1Node.name}
|
||||
seoName={l1Node.seoName}
|
||||
sx={{
|
||||
boxShadow: 4,
|
||||
width: '150px',
|
||||
height: '150px'
|
||||
}}
|
||||
/>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
display: { xs: 'block', md: 'none' } // Only show text below box on mobile if needed, or rely on box text
|
||||
}}
|
||||
>
|
||||
{/* Box already has text, so maybe no extra text needed here */}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{/* Descendants area */}
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
gap: 2
|
||||
}}>
|
||||
{descendants.map((cat) => (
|
||||
<CategoryBox
|
||||
key={cat.id}
|
||||
id={cat.id}
|
||||
name={cat.name}
|
||||
seoName={cat.seoName}
|
||||
sx={{
|
||||
width: '100px',
|
||||
height: '100px',
|
||||
minWidth: '100px',
|
||||
minHeight: '100px',
|
||||
boxShadow: 1,
|
||||
transition: 'transform 0.2s',
|
||||
'&:hover': { transform: 'scale(1.05)', boxShadow: 3 },
|
||||
fontSize: '0.9rem' // Smaller text for smaller boxes
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
const { categoryTree, loading } = this.state;
|
||||
|
||||
const content = (
|
||||
<Box>
|
||||
{loading ? (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
) : (
|
||||
<Box>
|
||||
{categoryTree && categoryTree.children && categoryTree.children.map((child) => (
|
||||
this.renderLevel1Section(child)
|
||||
))}
|
||||
{(!categoryTree || !categoryTree.children || categoryTree.children.length === 0) && (
|
||||
<Typography>Keine Kategorien gefunden.</Typography>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
|
||||
return <LegalPage title={t ? t('navigation.categories') : 'Kategorien'} content={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default withI18n()(CategoriesPage);
|
||||
@@ -30,28 +30,28 @@ const ResetPassword = () => {
|
||||
const tokenFromUrl = urlParams.get('token');
|
||||
|
||||
if (!tokenFromUrl) {
|
||||
setError('Kein gültiger Token gefunden. Bitte verwenden Sie den Link aus Ihrer E-Mail.');
|
||||
setError(t('auth.resetPassword.invalidToken'));
|
||||
} else {
|
||||
setToken(tokenFromUrl);
|
||||
}
|
||||
}, [location]);
|
||||
}, [location, t]);
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Validation
|
||||
if (!newPassword || !confirmPassword) {
|
||||
setError('Bitte füllen Sie alle Felder aus');
|
||||
setError(t('auth.errors.fillAllFields'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
setError('Das Passwort muss mindestens 8 Zeichen lang sein');
|
||||
setError(t('auth.passwordMinLength'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword !== confirmPassword) {
|
||||
setError('Die Passwörter stimmen nicht überein');
|
||||
setError(t('auth.errors.passwordsNotMatch'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ const ResetPassword = () => {
|
||||
}
|
||||
}, 3000);
|
||||
} else {
|
||||
setError(response.message || 'Fehler beim Zurücksetzen des Passworts');
|
||||
setError(response.message || t('auth.resetPassword.error'));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -87,7 +87,7 @@ const ResetPassword = () => {
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
||||
<LockResetIcon sx={{ fontSize: 48, color: 'primary.main', mb: 2 }} />
|
||||
<Typography component="h1" variant="h5" gutterBottom>
|
||||
Passwort zurücksetzen
|
||||
{t('auth.resetPassword.title')}
|
||||
</Typography>
|
||||
|
||||
{!token ? (
|
||||
@@ -97,7 +97,7 @@ const ResetPassword = () => {
|
||||
) : success ? (
|
||||
<Box sx={{ width: '100%', mt: 2 }}>
|
||||
<Alert severity="success" sx={{ mb: 2 }}>
|
||||
Ihr Passwort wurde erfolgreich zurückgesetzt! Sie werden in Kürze zur Anmeldung weitergeleitet...
|
||||
{t('auth.resetPassword.success')}
|
||||
</Alert>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<CircularProgress size={24} />
|
||||
@@ -116,7 +116,7 @@ const ResetPassword = () => {
|
||||
required
|
||||
fullWidth
|
||||
name="newPassword"
|
||||
label="Neues Passwort"
|
||||
label={t('auth.newPassword')}
|
||||
type="password"
|
||||
id="newPassword"
|
||||
autoComplete="new-password"
|
||||
@@ -130,7 +130,7 @@ const ResetPassword = () => {
|
||||
required
|
||||
fullWidth
|
||||
name="confirmPassword"
|
||||
label={t ? t('auth.confirmPassword') : 'Passwort bestätigen'}
|
||||
label={t('auth.confirmPassword')}
|
||||
type="password"
|
||||
id="confirmPassword"
|
||||
autoComplete="new-password"
|
||||
@@ -154,7 +154,7 @@ const ResetPassword = () => {
|
||||
{loading ? (
|
||||
<CircularProgress size={24} color="inherit" />
|
||||
) : (
|
||||
'Passwort zurücksetzen'
|
||||
t('auth.resetPassword.button')
|
||||
)}
|
||||
</Button>
|
||||
|
||||
@@ -164,7 +164,7 @@ const ResetPassword = () => {
|
||||
onClick={() => navigate('/')}
|
||||
sx={{ color: '#2e7d32' }}
|
||||
>
|
||||
Zurück zur Startseite
|
||||
{t('auth.backToHome')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user