From d1e7e7eacaf1cb780a1fe1202e948665a4694283 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joe=20K=C3=BCng?=
Date: Wed, 11 Mar 2026 15:07:12 +0100
Subject: [PATCH 1/5] feat(front-end): sitemap
---
frontend/public/robots.txt | 10 ++--
frontend/public/sitemap.xml | 10 ++++
.../pages/admin-home-media.component.html | 25 ++++++++-
.../pages/admin-home-media.component.scss | 56 +++++++++++++++++++
.../admin/pages/admin-home-media.component.ts | 53 +++++++++++++++++-
.../admin/pages/admin-shop.component.html | 42 +++++++-------
.../admin/pages/admin-shop.component.scss | 23 ++++++++
7 files changed, 190 insertions(+), 29 deletions(-)
diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt
index 6bd7b9c..b0af970 100644
--- a/frontend/public/robots.txt
+++ b/frontend/public/robots.txt
@@ -5,17 +5,19 @@ Disallow: /admin
Disallow: /admin/
Disallow: /*/admin
Disallow: /*/admin/
+Disallow: /order
Disallow: /order/
+Disallow: /*/order
Disallow: /*/order/
+Disallow: /co
Disallow: /co/
+Disallow: /*/co
Disallow: /*/co/
Disallow: /checkout
Disallow: /checkout/
+Disallow: /checkout/cad
Disallow: /*/checkout
Disallow: /*/checkout/
-Disallow: /shop
-Disallow: /shop/
-Disallow: /*/shop
-Disallow: /*/shop/
+Disallow: /*/checkout/cad
Sitemap: https://3d-fab.ch/sitemap.xml
diff --git a/frontend/public/sitemap.xml b/frontend/public/sitemap.xml
index a1195d2..c81cb56 100644
--- a/frontend/public/sitemap.xml
+++ b/frontend/public/sitemap.xml
@@ -73,6 +73,16 @@
weekly
0.8
+
+ https://3d-fab.ch/it/shop
+
+
+
+
+
+ weekly
+ 0.8
+
https://3d-fab.ch/it/about
diff --git a/frontend/src/app/features/admin/pages/admin-home-media.component.html b/frontend/src/app/features/admin/pages/admin-home-media.component.html
index 50474eb..ee1e79f 100644
--- a/frontend/src/app/features/admin/pages/admin-home-media.component.html
+++ b/frontend/src/app/features/admin/pages/admin-home-media.component.html
@@ -130,7 +130,7 @@
diff --git a/frontend/src/app/features/admin/pages/admin-home-media.component.scss b/frontend/src/app/features/admin/pages/admin-home-media.component.scss
index 7f70af2..c5b246c 100644
--- a/frontend/src/app/features/admin/pages/admin-home-media.component.scss
+++ b/frontend/src/app/features/admin/pages/admin-home-media.component.scss
@@ -27,6 +27,62 @@
gap: var(--space-1);
}
+.image-language-button {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35rem;
+ min-width: 3.15rem;
+ background: #ffffff;
+ color: var(--color-text-muted);
+}
+
+.image-language-button.empty {
+ opacity: 0.76;
+}
+
+.image-language-button.complete {
+ border-color: #b8ddc2;
+}
+
+.image-language-button.incomplete {
+ border-color: #e8c8c2;
+}
+
+.image-language-button.active {
+ background: #fff5b8;
+ border-color: var(--color-brand);
+ color: var(--color-text);
+ opacity: 1;
+}
+
+.image-language-button__label {
+ line-height: 1;
+}
+
+.image-language-button__state {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 1rem;
+ height: 1rem;
+ padding: 0 0.2rem;
+ border-radius: 999px;
+ background: rgba(0, 0, 0, 0.08);
+ font-size: 0.62rem;
+ font-weight: 800;
+ line-height: 1;
+}
+
+.image-language-button.complete .image-language-button__state {
+ background: #dcefdc;
+ color: #25603b;
+}
+
+.image-language-button.incomplete .image-language-button__state {
+ background: #f7ddd7;
+ color: #944329;
+}
+
.form-field--wide {
grid-column: 1 / -1;
}
diff --git a/frontend/src/app/features/admin/pages/admin-home-media.component.ts b/frontend/src/app/features/admin/pages/admin-home-media.component.ts
index 5358d24..4ad4866 100644
--- a/frontend/src/app/features/admin/pages/admin-home-media.component.ts
+++ b/frontend/src/app/features/admin/pages/admin-home-media.component.ts
@@ -17,12 +17,16 @@ type HomeSectionKey =
| 'capability-prototyping'
| 'capability-custom-parts'
| 'capability-small-series'
- | 'capability-cad';
+ | 'capability-cad'
+ | 'joe'
+ | 'matteo';
+
+type HomeMediaUsageType = 'HOME_SECTION' | 'ABOUT_MEMBER';
interface HomeMediaSectionConfig {
- usageType: 'HOME_SECTION';
+ usageType: HomeMediaUsageType;
usageKey: HomeSectionKey;
- groupId: 'galleries' | 'capabilities';
+ groupId: 'galleries' | 'capabilities' | 'about-members';
title: string;
preferredVariantName: 'card' | 'hero';
}
@@ -94,6 +98,10 @@ export class AdminHomeMediaComponent implements OnInit, OnDestroy {
id: 'capabilities',
title: 'Cosa puoi ottenere',
},
+ {
+ id: 'about-members',
+ title: 'Chi siamo',
+ },
];
readonly sectionConfigs: readonly HomeMediaSectionConfig[] = [
@@ -139,6 +147,20 @@ export class AdminHomeMediaComponent implements OnInit, OnDestroy {
title: 'Home: consulenza e CAD',
preferredVariantName: 'card',
},
+ {
+ usageType: 'ABOUT_MEMBER',
+ usageKey: 'joe',
+ groupId: 'about-members',
+ title: 'Chi siamo: Joe',
+ preferredVariantName: 'card',
+ },
+ {
+ usageType: 'ABOUT_MEMBER',
+ usageKey: 'matteo',
+ groupId: 'about-members',
+ title: 'Chi siamo: Matteo',
+ preferredVariantName: 'card',
+ },
];
sections: HomeMediaSectionView[] = [];
@@ -155,6 +177,8 @@ export class AdminHomeMediaComponent implements OnInit, OnDestroy {
'capability-custom-parts': this.createEmptyFormState(),
'capability-small-series': this.createEmptyFormState(),
'capability-cad': this.createEmptyFormState(),
+ joe: this.createEmptyFormState(),
+ matteo: this.createEmptyFormState(),
};
get configuredSectionCount(): number {
@@ -432,6 +456,25 @@ export class AdminHomeMediaComponent implements OnInit, OnDestroy {
);
}
+ isLanguageStarted(
+ sectionKey: HomeSectionKey,
+ language: AdminMediaLanguage,
+ ): boolean {
+ return this.isTranslationStarted(
+ this.getFormState(sectionKey).translations[language],
+ );
+ }
+
+ isLanguageIncomplete(
+ sectionKey: HomeSectionKey,
+ language: AdminMediaLanguage,
+ ): boolean {
+ return (
+ this.isLanguageStarted(sectionKey, language) &&
+ !this.isLanguageComplete(sectionKey, language)
+ );
+ }
+
getItemTranslation(
item: HomeMediaItem,
language: AdminMediaLanguage,
@@ -619,6 +662,10 @@ export class AdminHomeMediaComponent implements OnInit, OnDestroy {
return !!translation.title.trim() && !!translation.altText.trim();
}
+ private isTranslationStarted(translation: AdminMediaTranslation): boolean {
+ return !!translation.title.trim() || !!translation.altText.trim();
+ }
+
private validateTranslations(
translations: Record,
): string | null {
diff --git a/frontend/src/app/features/admin/pages/admin-shop.component.html b/frontend/src/app/features/admin/pages/admin-shop.component.html
index 039c9d7..2330147 100644
--- a/frontend/src/app/features/admin/pages/admin-shop.component.html
+++ b/frontend/src/app/features/admin/pages/admin-shop.component.html
@@ -8,25 +8,29 @@
-